summaryrefslogtreecommitdiffstats
path: root/include/asm-mips/stackframe.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /include/asm-mips/stackframe.h
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/asm-mips/stackframe.h')
-rw-r--r--include/asm-mips/stackframe.h341
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 */