r4k_switch.S 6.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6
/*
 * 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, 1998, 1999, 2002, 2003 Ralf Baechle
7
 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16
 * Copyright (C) 1994, 1995, 1996, by Andreas Busse
 * Copyright (C) 1999 Silicon Graphics, Inc.
 * Copyright (C) 2000 MIPS Technologies, Inc.
 *    written by Carsten Langgaard, carstenl@mips.com
 */
#include <asm/asm.h>
#include <asm/cachectl.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
17
#include <asm/asm-offsets.h>
L
Linus Torvalds 已提交
18 19 20 21 22 23 24
#include <asm/pgtable-bits.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/thread_info.h>

#include <asm/asmmacro.h>

25 26 27
/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
#undef fp

L
Linus Torvalds 已提交
28 29 30 31 32 33
/*
 * Offset to the current process status flags, the first 32 bytes of the
 * stack are not used.
 */
#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)

D
David Daney 已提交
34
#ifndef USE_ALTERNATE_RESUME_IMPL
L
Linus Torvalds 已提交
35 36
/*
 * task_struct *resume(task_struct *prev, task_struct *next,
37
 *		       struct thread_info *next_ti, s32 fp_save)
L
Linus Torvalds 已提交
38 39 40
 */
	.align	5
	LEAF(resume)
41 42
	mfc0	t1, CP0_STATUS
	LONG_S	t1, THREAD_STATUS(a0)
L
Linus Torvalds 已提交
43 44 45 46
	cpu_save_nonscratch a0
	LONG_S	ra, THREAD_REG31(a0)

	/*
47 48 49 50 51
	 * Check whether we need to save any FP context. FP context is saved
	 * iff the process has used the context with the scalar FPU or the MSA
	 * ASE in the current time slice, as indicated by _TIF_USEDFPU and
	 * _TIF_USEDMSA respectively. switch_to will have set fp_save
	 * accordingly to an FP_SAVE_ enum value.
L
Linus Torvalds 已提交
52
	 */
53
	beqz	a3, 2f
L
Linus Torvalds 已提交
54 55

	/*
56 57 58 59
	 * We do. Clear the saved CU1 bit for prev, such that next time it is
	 * scheduled it will start in userland with the FPU disabled. If the
	 * task uses the FPU then it will be enabled again via the do_cpu trap.
	 * This allows us to lazily restore the FP context.
L
Linus Torvalds 已提交
60
	 */
61
	PTR_L	t3, TASK_THREAD_INFO(a0)
L
Linus Torvalds 已提交
62 63 64 65 66
	LONG_L	t0, ST_OFF(t3)
	li	t1, ~ST0_CU1
	and	t0, t0, t1
	LONG_S	t0, ST_OFF(t3)

67 68 69
	/* Check whether we're saving scalar or vector context. */
	bgtz	a3, 1f

70
	/* Save 128b MSA vector context + scalar FP control & status. */
71 72
	.set push
	SET_HARDFLOAT
73
	cfc1	t1, fcr31
74
	msa_save_all	a0
75 76
	.set pop	/* SET_HARDFLOAT */

77
	sw	t1, THREAD_FCR31(a0)
78 79 80
	b	2f

1:	/* Save 32b/64b scalar FP context. */
81 82
	fpu_save_double a0 t0 t1		# c0_status passed in t0
						# clobbers t1
83
2:
L
Linus Torvalds 已提交
84

85
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
86
	PTR_LA	t8, __stack_chk_guard
87 88 89 90
	LONG_L	t9, TASK_STACK_CANARY(a1)
	LONG_S	t9, 0(t8)
#endif

L
Linus Torvalds 已提交
91 92 93 94 95 96 97
	/*
	 * The order of restoring the registers takes care of the race
	 * updating $28, $29 and kernelsp without disabling ints.
	 */
	move	$28, a2
	cpu_restore_nonscratch a1

98
	PTR_ADDU	t0, $28, _THREAD_SIZE - 32
L
Linus Torvalds 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111
	set_saved_sp	t0, t1, t2
	mfc0	t1, CP0_STATUS		/* Do we really need this? */
	li	a3, 0xff01
	and	t1, a3
	LONG_L	a2, THREAD_STATUS(a1)
	nor	a3, $0, a3
	and	a2, a3
	or	a2, t1
	mtc0	a2, CP0_STATUS
	move	v0, a0
	jr	ra
	END(resume)

D
David Daney 已提交
112 113
#endif /* USE_ALTERNATE_RESUME_IMPL */

L
Linus Torvalds 已提交
114 115 116 117
/*
 * Save a thread's fp context.
 */
LEAF(_save_fp)
118 119
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
		defined(CONFIG_CPU_MIPS32_R6)
120
	mfc0	t0, CP0_STATUS
L
Linus Torvalds 已提交
121
#endif
122
	fpu_save_double a0 t0 t1		# clobbers t1
L
Linus Torvalds 已提交
123 124 125 126 127 128 129
	jr	ra
	END(_save_fp)

/*
 * Restore a thread's fp context.
 */
LEAF(_restore_fp)
130 131
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
		defined(CONFIG_CPU_MIPS32_R6)
132 133 134
	mfc0	t0, CP0_STATUS
#endif
	fpu_restore_double a0 t0 t1		# clobbers t1
L
Linus Torvalds 已提交
135 136 137
	jr	ra
	END(_restore_fp)

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
#ifdef CONFIG_CPU_HAS_MSA

/*
 * Save a thread's MSA vector context.
 */
LEAF(_save_msa)
	msa_save_all	a0
	jr	ra
	END(_save_msa)

/*
 * Restore a thread's MSA vector context.
 */
LEAF(_restore_msa)
	msa_restore_all	a0
	jr	ra
	END(_restore_msa)

156 157 158 159 160
LEAF(_init_msa_upper)
	msa_init_all_upper
	jr	ra
	END(_init_msa_upper)

161 162
#endif

L
Linus Torvalds 已提交
163 164 165 166 167
/*
 * Load the FPU with signalling NANS.  This bit pattern we're using has
 * the property that no matter whether considered as single or as double
 * precision represents signaling NANS.
 *
168
 * The value to initialize fcr31 to comes in $a0.
L
Linus Torvalds 已提交
169 170
 */

171 172 173
	.set push
	SET_HARDFLOAT

L
Linus Torvalds 已提交
174 175 176 177 178
LEAF(_init_fpu)
	mfc0	t0, CP0_STATUS
	li	t1, ST0_CU1
	or	t0, t1
	mtc0	t0, CP0_STATUS
179
	enable_fpu_hazard
L
Linus Torvalds 已提交
180

181
	ctc1	a0, fcr31
L
Linus Torvalds 已提交
182 183 184

	li	t1, -1				# SNaN

185
#ifdef CONFIG_64BIT
L
Linus Torvalds 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	sll	t0, t0, 5
	bgez	t0, 1f				# 16 / 32 register mode?

	dmtc1	t1, $f1
	dmtc1	t1, $f3
	dmtc1	t1, $f5
	dmtc1	t1, $f7
	dmtc1	t1, $f9
	dmtc1	t1, $f11
	dmtc1	t1, $f13
	dmtc1	t1, $f15
	dmtc1	t1, $f17
	dmtc1	t1, $f19
	dmtc1	t1, $f21
	dmtc1	t1, $f23
	dmtc1	t1, $f25
	dmtc1	t1, $f27
	dmtc1	t1, $f29
	dmtc1	t1, $f31
1:
#endif
207

L
Linus Torvalds 已提交
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
#ifdef CONFIG_CPU_MIPS32
	mtc1	t1, $f0
	mtc1	t1, $f1
	mtc1	t1, $f2
	mtc1	t1, $f3
	mtc1	t1, $f4
	mtc1	t1, $f5
	mtc1	t1, $f6
	mtc1	t1, $f7
	mtc1	t1, $f8
	mtc1	t1, $f9
	mtc1	t1, $f10
	mtc1	t1, $f11
	mtc1	t1, $f12
	mtc1	t1, $f13
	mtc1	t1, $f14
	mtc1	t1, $f15
	mtc1	t1, $f16
	mtc1	t1, $f17
	mtc1	t1, $f18
	mtc1	t1, $f19
	mtc1	t1, $f20
	mtc1	t1, $f21
	mtc1	t1, $f22
	mtc1	t1, $f23
	mtc1	t1, $f24
	mtc1	t1, $f25
	mtc1	t1, $f26
	mtc1	t1, $f27
	mtc1	t1, $f28
	mtc1	t1, $f29
	mtc1	t1, $f30
	mtc1	t1, $f31
241

242
#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6)
243
	.set    push
244
	.set    MIPS_ISA_LEVEL_RAW
245
	.set	fp=64
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 278 279 280 281
	sll     t0, t0, 5			# is Status.FR set?
	bgez    t0, 1f				# no: skip setting upper 32b

	mthc1   t1, $f0
	mthc1   t1, $f1
	mthc1   t1, $f2
	mthc1   t1, $f3
	mthc1   t1, $f4
	mthc1   t1, $f5
	mthc1   t1, $f6
	mthc1   t1, $f7
	mthc1   t1, $f8
	mthc1   t1, $f9
	mthc1   t1, $f10
	mthc1   t1, $f11
	mthc1   t1, $f12
	mthc1   t1, $f13
	mthc1   t1, $f14
	mthc1   t1, $f15
	mthc1   t1, $f16
	mthc1   t1, $f17
	mthc1   t1, $f18
	mthc1   t1, $f19
	mthc1   t1, $f20
	mthc1   t1, $f21
	mthc1   t1, $f22
	mthc1   t1, $f23
	mthc1   t1, $f24
	mthc1   t1, $f25
	mthc1   t1, $f26
	mthc1   t1, $f27
	mthc1   t1, $f28
	mthc1   t1, $f29
	mthc1   t1, $f30
	mthc1   t1, $f31
1:	.set    pop
282
#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */
L
Linus Torvalds 已提交
283
#else
284
	.set	MIPS_ISA_ARCH_LEVEL_RAW
L
Linus Torvalds 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
	dmtc1	t1, $f0
	dmtc1	t1, $f2
	dmtc1	t1, $f4
	dmtc1	t1, $f6
	dmtc1	t1, $f8
	dmtc1	t1, $f10
	dmtc1	t1, $f12
	dmtc1	t1, $f14
	dmtc1	t1, $f16
	dmtc1	t1, $f18
	dmtc1	t1, $f20
	dmtc1	t1, $f22
	dmtc1	t1, $f24
	dmtc1	t1, $f26
	dmtc1	t1, $f28
	dmtc1	t1, $f30
#endif
	jr	ra
	END(_init_fpu)
304 305

	.set pop	/* SET_HARDFLOAT */