summaryrefslogtreecommitdiff
path: root/release/src/linux/linux/include/asm-mips64/stackframe.h
blob: 7c4d532a98cd8a6aa3453f458f699a18a61f7e01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
 * 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, 1999 Ralf Baechle
 * Copyright (C) 1994, 1995, 1996 Paul M. Antoine.
 * Copyright (C) 1999 Silicon Graphics, Inc.
 */
#ifndef _ASM_STACKFRAME_H
#define _ASM_STACKFRAME_H

#include <linux/config.h>

#include <asm/asm.h>
#include <asm/offset.h>
#include <asm/processor.h>
#include <asm/addrspace.h>

#ifndef __ASSEMBLY__

#define __str2(x) #x
#define __str(x) __str2(x)

#define save_static(frame)                               \
	__asm__ __volatile__(                            \
		"sd\t$16,"__str(PT_R16)"(%0)\n\t"        \
		"sd\t$17,"__str(PT_R17)"(%0)\n\t"        \
		"sd\t$18,"__str(PT_R18)"(%0)\n\t"        \
		"sd\t$19,"__str(PT_R19)"(%0)\n\t"        \
		"sd\t$20,"__str(PT_R20)"(%0)\n\t"        \
		"sd\t$21,"__str(PT_R21)"(%0)\n\t"        \
		"sd\t$22,"__str(PT_R22)"(%0)\n\t"        \
		"sd\t$23,"__str(PT_R23)"(%0)\n\t"        \
		"sd\t$30,"__str(PT_R30)"(%0)\n\t"        \
		: /* No outputs */                       \
		: "r" (frame))

#endif /* !__ASSEMBLY__ */

#ifdef __ASSEMBLY__

		.macro	SAVE_AT
		.set	push
		.set	noat
		sd	$1, PT_R1(sp)
		.set	pop
		.endm

		.macro	SAVE_TEMP
		mfhi	v1
		sd	$8, PT_R8(sp)
		sd	$9, PT_R9(sp)
		sd	v1, PT_HI(sp)
		mflo	v1
		sd	$10, PT_R10(sp)
		sd	$11, PT_R11(sp)
		sd	v1,  PT_LO(sp)
		sd	$12, PT_R12(sp)
		sd	$13, PT_R13(sp)
		sd	$14, PT_R14(sp)
		sd	$15, PT_R15(sp)
		sd	$24, PT_R24(sp)
		.endm

		.macro	SAVE_STATIC
		sd	$16, PT_R16(sp)
		sd	$17, PT_R17(sp)
		sd	$18, PT_R18(sp)
		sd	$19, PT_R19(sp)
		sd	$20, PT_R20(sp)
		sd	$21, PT_R21(sp)
		sd	$22, PT_R22(sp)
		sd	$23, PT_R23(sp)
		sd	$30, PT_R30(sp)
		.endm

#ifdef CONFIG_SMP
		.macro	get_saved_sp	/* R10000 variation */
#ifdef CONFIG_CPU_SB1
		dmfc0	k1, CP0_WATCHLO
#else
		mfc0	k0, CP0_WATCHLO
		mfc0	k1, CP0_WATCHHI
		dsll32	k0, k0, 0	/* Get rid of sign extension */
		dsrl32	k0, k0, 0	/* Get rid of sign extension */
		dsll32	k1, k1, 0
		or	k1, k1, k0
		li	k0, K0BASE
		or	k1, k1, k0
#endif
		.endm

		.macro	set_saved_sp	stackp temp
#ifdef CONFIG_CPU_SB1
		dmtc0	\stackp, CP0_WATCHLO
#else
		mtc0	\stackp, CP0_WATCHLO
		dsrl32	\temp, \stackp, 0
		mtc0	\temp, CP0_WATCHHI
#endif
		.endm

		.macro	declare_saved_sp
		# empty, stackpointer stored in a register
		.endm
#else
		.macro	get_saved_sp	/* Uniprocessor variation */
		lui	k1, %hi(kernelsp)
		ld	k1, %lo(kernelsp)(k1)
		.endm

		.macro	set_saved_sp	stackp temp
		sd	\stackp, kernelsp
		.endm

		.macro	declare_saved_sp
		.comm	kernelsp, 8, 8			# current stackpointer
		.endm
#endif

		.macro	SAVE_SOME
		.set	push
		.set	reorder
		mfc0	k0, CP0_STATUS
		sll	k0, 3		/* extract cu0 bit */
		.set	noreorder
		bltz	k0, 8f
		 move	k1, sp
		.set	reorder
		/* Called from user mode, new stack. */
		get_saved_sp
8:		move	k0, sp
		dsubu	sp, k1, PT_SIZE
		sd	k0, PT_R29(sp)
		sd	$3, PT_R3(sp)
		sd	$0, PT_R0(sp)
		mfc0	v1, CP0_STATUS
		sd	$2, PT_R2(sp)
		sd	v1, PT_STATUS(sp)
		sd	$4, PT_R4(sp)
		mfc0	v1, CP0_CAUSE
		sd	$5, PT_R5(sp)
		sd	v1, PT_CAUSE(sp)
		sd	$6, PT_R6(sp)
		dmfc0	v1, CP0_EPC
		sd	$7, PT_R7(sp)
		sd	v1, PT_EPC(sp)
		sd	$25, PT_R25(sp)
		sd	$28, PT_R28(sp)
		sd	$31, PT_R31(sp)
		ori	$28, sp, 0x3fff
		xori	$28, 0x3fff
		.set	pop
		.endm

		.macro	SAVE_ALL
		SAVE_SOME
		SAVE_AT
		SAVE_TEMP
		SAVE_STATIC
		.endm

		.macro	RESTORE_AT
		.set	push
		.set	noat
		ld	$1,  PT_R1(sp)
		.set	pop
		.endm

		.macro	RESTORE_SP
		ld	sp,  PT_R29(sp)
		.endm

		.macro	RESTORE_TEMP
		ld	$24, PT_LO(sp)
		ld	$8, PT_R8(sp)
		ld	$9, PT_R9(sp)
		mtlo	$24
		ld	$24, PT_HI(sp)
		ld	$10, PT_R10(sp)
		ld	$11, PT_R11(sp)
		mthi	$24
		ld	$12, PT_R12(sp)
		ld	$13, PT_R13(sp)
		ld	$14, PT_R14(sp)
		ld	$15, PT_R15(sp)
		ld	$24, PT_R24(sp)
		.endm

		.macro	RESTORE_STATIC
		ld	$16, PT_R16(sp)
		ld	$17, PT_R17(sp)
		ld	$18, PT_R18(sp)
		ld	$19, PT_R19(sp)
		ld	$20, PT_R20(sp)
		ld	$21, PT_R21(sp)
		ld	$22, PT_R22(sp)
		ld	$23, PT_R23(sp)
		ld	$30, PT_R30(sp)
		.endm

		.macro	RESTORE_SOME
		.set	push
		.set	reorder
		mfc0	t0, CP0_STATUS
		.set	pop
		ori	t0, 0x1f
		xori	t0, 0x1f
		mtc0	t0, CP0_STATUS
		li	v1, 0xff00
		and	t0, v1
		ld	v0, PT_STATUS(sp)
		nor	v1, $0, v1
		and	v0, v1
		or	v0, t0
		mtc0	v0, CP0_STATUS
		ld	v1, PT_EPC(sp)
		dmtc0	v1, CP0_EPC
		ld	$31, PT_R31(sp)
		ld	$28, PT_R28(sp)
		ld	$25, PT_R25(sp)
		ld	$7,  PT_R7(sp)
		ld	$6,  PT_R6(sp)
		ld	$5,  PT_R5(sp)
		ld	$4,  PT_R4(sp)
		ld	$3,  PT_R3(sp)
		ld	$2,  PT_R2(sp)
		.endm

		.macro	RESTORE_ALL
		RESTORE_SOME
		RESTORE_AT
		RESTORE_TEMP
		RESTORE_STATIC
		RESTORE_SP
		.endm

/*
 * Move to kernel mode and disable interrupts.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
		.macro	CLI
		mfc0	t0, CP0_STATUS
		li	t1, ST0_CU0|0x1f
		or	t0, t1
		xori	t0, 0x1f
		mtc0	t0, CP0_STATUS
		.endm

/*
 * Move to kernel mode and enable interrupts.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
		.macro	STI
		mfc0	t0, CP0_STATUS
		li	t1, ST0_CU0 | 0x1f
		or	t0, t1
		xori	t0, 0x1e
		mtc0	t0, CP0_STATUS
		.endm

/*
 * Just move to kernel mode and leave interrupts as they are.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
		.macro	KMODE
		mfc0	t0, CP0_STATUS
		li	t1, ST0_CU0 | 0x1e
		or	t0, t1
		xori	t0, 0x1e
		mtc0	t0, CP0_STATUS
		.endm

#endif /* __ASSEMBLY__ */

#endif /* _ASM_STACKFRAME_H */