diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /include/asm-mips/stackframe.h | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/asm-mips/stackframe.h')
-rw-r--r-- | include/asm-mips/stackframe.h | 341 |
1 files changed, 265 insertions, 76 deletions
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index b3b69f3c6..3cdbb61ef 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h @@ -1,109 +1,141 @@ /* - * include/asm-mips/stackframe.h + * Makefile for MIPS Linux main source directory * - * Copyright (C) 1994, 1995 Waldorf Electronics - * written by Ralf Baechle + * 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) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine. + * Additional R3000 support by Didier Frick <dfrick@dial.eunet.ch> + * for ACN S.A, Copyright (C) 1996 by ACN S.A */ - #ifndef __ASM_MIPS_STACKFRAME_H #define __ASM_MIPS_STACKFRAME_H +#include <asm/sgidefs.h> +#include <asm/asm.h> + /* * Stack layout for all exceptions: * * ptrace needs to have all regs on the stack. If the order here is changed, * it needs to be updated in include/asm-mips/ptrace.h * - * The first PTRSIZE*5 bytes are argument save space for C subroutines. + * The first PTRSIZE*6 bytes are argument save space for C subroutines. + * zero doesn't get saved; it's just a placeholder. */ -#define FR_REG1 (PTRSIZE*5) -#define FR_REG2 ((FR_REG1) + 4) -#define FR_REG3 ((FR_REG2) + 4) -#define FR_REG4 ((FR_REG3) + 4) -#define FR_REG5 ((FR_REG4) + 4) -#define FR_REG6 ((FR_REG5) + 4) -#define FR_REG7 ((FR_REG6) + 4) -#define FR_REG8 ((FR_REG7) + 4) -#define FR_REG9 ((FR_REG8) + 4) -#define FR_REG10 ((FR_REG9) + 4) -#define FR_REG11 ((FR_REG10) + 4) -#define FR_REG12 ((FR_REG11) + 4) -#define FR_REG13 ((FR_REG12) + 4) -#define FR_REG14 ((FR_REG13) + 4) -#define FR_REG15 ((FR_REG14) + 4) -#define FR_REG16 ((FR_REG15) + 4) -#define FR_REG17 ((FR_REG16) + 4) -#define FR_REG18 ((FR_REG17) + 4) -#define FR_REG19 ((FR_REG18) + 4) -#define FR_REG20 ((FR_REG19) + 4) -#define FR_REG21 ((FR_REG20) + 4) -#define FR_REG22 ((FR_REG21) + 4) -#define FR_REG23 ((FR_REG22) + 4) -#define FR_REG24 ((FR_REG23) + 4) -#define FR_REG25 ((FR_REG24) + 4) +#define FR_REG0 (SZREG*6) +#define FR_REG1 ((FR_REG0) + SZREG) +#define FR_REG2 ((FR_REG1) + SZREG) +#define FR_REG3 ((FR_REG2) + SZREG) +#define FR_REG4 ((FR_REG3) + SZREG) +#define FR_REG5 ((FR_REG4) + SZREG) +#define FR_REG6 ((FR_REG5) + SZREG) +#define FR_REG7 ((FR_REG6) + SZREG) +#define FR_REG8 ((FR_REG7) + SZREG) +#define FR_REG9 ((FR_REG8) + SZREG) +#define FR_REG10 ((FR_REG9) + SZREG) +#define FR_REG11 ((FR_REG10) + SZREG) +#define FR_REG12 ((FR_REG11) + SZREG) +#define FR_REG13 ((FR_REG12) + SZREG) +#define FR_REG14 ((FR_REG13) + SZREG) +#define FR_REG15 ((FR_REG14) + SZREG) +#define FR_REG16 ((FR_REG15) + SZREG) +#define FR_REG17 ((FR_REG16) + SZREG) +#define FR_REG18 ((FR_REG17) + SZREG) +#define FR_REG19 ((FR_REG18) + SZREG) +#define FR_REG20 ((FR_REG19) + SZREG) +#define FR_REG21 ((FR_REG20) + SZREG) +#define FR_REG22 ((FR_REG21) + SZREG) +#define FR_REG23 ((FR_REG22) + SZREG) +#define FR_REG24 ((FR_REG23) + SZREG) +#define FR_REG25 ((FR_REG24) + SZREG) /* - * $26 (k0) and $27 (k1) not saved + * $26 (k0) and $27 (k1) not saved - just placeholders */ -#define FR_REG28 ((FR_REG25) + 4) -#define FR_REG29 ((FR_REG28) + 4) -#define FR_REG30 ((FR_REG29) + 4) -#define FR_REG31 ((FR_REG30) + 4) +#define FR_REG26 ((FR_REG25) + SZREG) +#define FR_REG27 ((FR_REG26) + SZREG) + +#define FR_REG28 ((FR_REG27) + SZREG) +#define FR_REG29 ((FR_REG28) + SZREG) +#define FR_REG30 ((FR_REG29) + SZREG) +#define FR_REG31 ((FR_REG30) + SZREG) /* * Saved special registers */ -#define FR_LO ((FR_REG31) + 4) -#define FR_HI ((FR_LO) + 4) +#define FR_LO ((FR_REG31) + SZREG) +#define FR_HI ((FR_LO) + SZREG) +#define FR_ORIG_REG2 ((FR_HI) + SZREG) +#define FR_ORIG_REG7 ((FR_ORIG_REG2) + SZREG) /* * Saved cp0 registers follow */ -#define FR_STATUS ((FR_HI) + 4) -#define FR_EPC ((FR_STATUS) + 4) -#define FR_CAUSE ((FR_EPC) + 4) +#define FR_EPC ((FR_ORIG_REG7) + SZREG) +#define FR_BADVADDR ((FR_EPC) + SZREG) +#define FR_STATUS ((FR_BADVADDR) + SZREG) +#define FR_CAUSE ((FR_STATUS) + 4) /* - * Some goodies... + * Size of stack frame, word/double word alignment */ -#define FR_INTERRUPT ((FR_CAUSE) + 4) -#define FR_ORIG_REG2 ((FR_INTERRUPT) + 4) -#define FR_PAD1 ((FR_ORIG_REG2) + 4) +#define FR_SIZE (((FR_CAUSE + 4) + ALSZ) & ALMASK) /* - * Size of stack frame, word/double word alignment + * Load the global pointer. Only for ELF executables global pointer + * optimization is possible, so we only load the global pointer for + * ELF kernels. */ -#define FR_SIZE ((((FR_PAD1) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1)) +#if 0 +#define LOAD_GP la gp,_gp +#else +#define LOAD_GP +#endif -#ifdef __R4000__ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) #define SAVE_ALL \ mfc0 k0,CP0_STATUS; \ - sll k0,3; /* extract cu0 bit */ \ - bltz k0,8f; \ + li k1,ST0_CU0; \ + and k0,k1; \ + bnez k0,8f; \ move k1,sp; \ + nop; \ /* \ * Called from user mode, new stack \ */ \ - lui k1,%hi(kernelsp); \ - lw k1,%lo(kernelsp)(k1); \ + lw k1,kernelsp; \ 8: move k0,sp; \ subu sp,k1,FR_SIZE; \ sw k0,FR_REG29(sp); \ - sw $2,FR_REG2(sp); \ - sw $2,FR_ORIG_REG2(sp); \ - mfc0 v0,CP0_STATUS; \ - sw v0,FR_STATUS(sp); \ - mfc0 v0,CP0_CAUSE; \ - sw v0,FR_CAUSE(sp); \ - mfc0 v0,CP0_EPC; \ - sw v0,FR_EPC(sp); \ - mfhi v0; \ - sw v0,FR_HI(sp); \ - mflo v0; \ - sw v0,FR_LO(sp); \ - sw $1,FR_REG1(sp); \ sw $3,FR_REG3(sp); \ + mfc0 $3,CP0_STATUS; \ + nop; \ + sw $3,FR_STATUS(sp); \ + li k1,ST0_CU0; \ + or k1,$3; \ + mtc0 k1,CP0_STATUS; \ + nop; \ + mfc0 $3,CP0_ENTRYHI; \ + nop; \ + sw $3,FR_ENTRYHI(sp); \ + mfc0 $3,CP0_CAUSE; \ + nop; \ + sw $3,FR_CAUSE(sp); \ + mfc0 $3,CP0_EPC; \ + nop; \ + sw $3,FR_EPC(sp); \ + mfc0 $3,CP0_BADVADDR; \ + nop; \ + sw $3,FR_BADVADDR(sp); \ + mfhi $3; \ + sw $3,FR_HI(sp); \ + mflo $3; \ + sw $3,FR_LO(sp); \ + sw $1,FR_REG1(sp); \ + sw $2,FR_REG2(sp); \ sw $4,FR_REG4(sp); \ sw $5,FR_REG5(sp); \ sw $6,FR_REG6(sp); \ @@ -128,24 +160,25 @@ sw $25,FR_REG25(sp); \ sw $28,FR_REG28(sp); \ sw $30,FR_REG30(sp); \ - sw $31,FR_REG31(sp) + sw $31,FR_REG31(sp); \ + LOAD_GP /* * Note that we restore the IE flags from stack. This means * that a modified IE mask will be nullified. */ -#define RESTORE_ALL \ - .set mips3; \ +/* + * FIXME: Don't need to clear these bits on R[236]000's?? + * mfc0 t0,CP0_STATUS; \ ori t0,0x1f; \ xori t0,0x1f; \ mtc0 t0,CP0_STATUS; \ - \ - lw v0,FR_STATUS(sp); \ + */ +#define RESTORE_ALL \ lw v1,FR_LO(sp); \ - mtc0 v0,CP0_STATUS; \ - mtlo v1; \ lw v0,FR_HI(sp); \ + mtlo v1; \ lw v1,FR_EPC(sp); \ mthi v0; \ mtc0 v1,CP0_EPC; \ @@ -177,13 +210,169 @@ lw $3,FR_REG3(sp); \ lw $2,FR_REG2(sp); \ lw $1,FR_REG1(sp); \ - lw sp,FR_REG29(sp); /* Deallocate stack */ \ - .set mips0 + lw k1,FR_STATUS(sp); \ + lw sp,FR_REG29(sp); \ + ori k1,3; \ + xori k1,3; \ + mtc0 k1,CP0_STATUS; \ + nop + +/* + * We disable interrupts when restoring the status register because: + * 1) the ret_from_syscall routine uses k0/k1 to preserve values around + * the RESTORE_ALL + * 2) the rfe instruction will restore the IE and KU flags to their + * previous value. + */ + +#define CLI \ + mfc0 t1,$12; \ + li t0,ST0_CU0|1; \ + or t1,t1,t0; \ + xori t1,1; \ + mtc0 t1,$12; \ + nop; \ + nop + +#define STI \ + mfc0 t1,$12; \ + li t0,ST0_CU0|1; \ + or t1,t1,t0; \ + mtc0 t1,$12; \ + nop; \ + nop + +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */ -#else /* !defined (__R4000__) */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS5) -#error "Implement SAVE_ALL and RESTORE_ALL!" +#define SAVE_ALL \ + mfc0 k0,CP0_STATUS; \ + sll k0,3; /* extract cu0 bit */ \ + bltz k0,8f; \ + move k1,sp; \ + /* \ + * Called from user mode, new stack \ + */ \ + lw k1,kernelsp; \ +8: move k0,sp; \ + subu sp,k1,FR_SIZE; \ + sd k0,FR_REG29(sp); \ + sd $3,FR_REG3(sp); \ + mfc0 $3,CP0_STATUS; \ + sw $3,FR_STATUS(sp); \ + mfc0 $3,CP0_CAUSE; \ + sw $3,FR_CAUSE(sp); \ + dmfc0 $3,CP0_EPC; \ + sd $3,FR_EPC(sp); \ + mfhi $3; \ + sd $3,FR_HI(sp); \ + mflo $3; \ + sd $3,FR_LO(sp); \ + sd $1,FR_REG1(sp); \ + sd $2,FR_REG2(sp); \ + sd $4,FR_REG4(sp); \ + sd $5,FR_REG5(sp); \ + sd $6,FR_REG6(sp); \ + sd $7,FR_REG7(sp); \ + sd $8,FR_REG8(sp); \ + sd $9,FR_REG9(sp); \ + sd $10,FR_REG10(sp); \ + sd $11,FR_REG11(sp); \ + sd $12,FR_REG12(sp); \ + sd $13,FR_REG13(sp); \ + sd $14,FR_REG14(sp); \ + sd $15,FR_REG15(sp); \ + sd $16,FR_REG16(sp); \ + sd $17,FR_REG17(sp); \ + sd $18,FR_REG18(sp); \ + sd $19,FR_REG19(sp); \ + sd $20,FR_REG20(sp); \ + sd $21,FR_REG21(sp); \ + sd $22,FR_REG22(sp); \ + sd $23,FR_REG23(sp); \ + sd $24,FR_REG24(sp); \ + sd $25,FR_REG25(sp); \ + sd $28,FR_REG28(sp); \ + sd $30,FR_REG30(sp); \ + sd $31,FR_REG31(sp); \ + LOAD_GP + +/* + * Note that we restore the IE flags from stack. This means + * that a modified IE mask will be nullified. + */ +#define RESTORE_ALL \ + mfc0 t0,CP0_STATUS; \ + ori t0,0x1f; \ + xori t0,0x1f; \ + mtc0 t0,CP0_STATUS; \ + \ + lw v0,FR_STATUS(sp); \ + ld v1,FR_LO(sp); \ + mtc0 v0,CP0_STATUS; \ + mtlo v1; \ + ld v0,FR_HI(sp); \ + ld v1,FR_EPC(sp); \ + mthi v0; \ + dmtc0 v1,CP0_EPC; \ + ld $31,FR_REG31(sp); \ + ld $30,FR_REG30(sp); \ + ld $28,FR_REG28(sp); \ + ld $25,FR_REG25(sp); \ + ld $24,FR_REG24(sp); \ + ld $23,FR_REG23(sp); \ + ld $22,FR_REG22(sp); \ + ld $21,FR_REG21(sp); \ + ld $20,FR_REG20(sp); \ + ld $19,FR_REG19(sp); \ + ld $18,FR_REG18(sp); \ + ld $17,FR_REG17(sp); \ + ld $16,FR_REG16(sp); \ + ld $15,FR_REG15(sp); \ + ld $14,FR_REG14(sp); \ + ld $13,FR_REG13(sp); \ + ld $12,FR_REG12(sp); \ + ld $11,FR_REG11(sp); \ + ld $10,FR_REG10(sp); \ + ld $9,FR_REG9(sp); \ + ld $8,FR_REG8(sp); \ + ld $7,FR_REG7(sp); \ + ld $6,FR_REG6(sp); \ + ld $5,FR_REG5(sp); \ + ld $4,FR_REG4(sp); \ + ld $3,FR_REG3(sp); \ + ld $2,FR_REG2(sp); \ + ld $1,FR_REG1(sp); \ + ld sp,FR_REG29(sp) /* Deallocate stack */ \ + +/* + * Move to kernel mode and disable interrupts. + * Set cp0 enable bit as sign that we're running on the kernel stack + */ +#define CLI \ + mfc0 t0,CP0_STATUS; \ + li t1,ST0_CU0|0x1f; \ + or t0,t1; \ + xori t0,0x1f; \ + mtc0 t0,CP0_STATUS + +/* + * Move to kernel mode and enable interrupts. + * Set cp0 enable bit as sign that we're running on the kernel stack + * + * Note that the mtc0 will be effective on R4000 pipeline stage 7. This + * means that another three instructions will be executed with interrupts + * disabled. Arch/mips/mips3/r4xx0.S makes use of this fact. + */ +#define STI \ + mfc0 t0,CP0_STATUS; \ + li t1,ST0_CU0|0x1f; \ + or t0,t1; \ + xori t0,0x1e; \ + mtc0 t0,CP0_STATUS -#endif /* !defined (__R4000__) */ +#endif /* _MIPS_ISA >= MIPS3 */ #endif /* __ASM_MIPS_STACKFRAME_H */ |