FreeBSD/Linux Kernel Cross Reference
sys/mips/mips/swtch.S
1 /* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Digital Equipment Corporation and Ralph Campbell.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Copyright (C) 1989 Digital Equipment Corporation.
34 * Permission to use, copy, modify, and distribute this software and
35 * its documentation for any purpose and without fee is hereby granted,
36 * provided that the above copyright notice appears in all copies.
37 * Digital Equipment Corporation makes no representations about the
38 * suitability of this software for any purpose. It is provided "as is"
39 * without express or implied warranty.
40 *
41 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
42 * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL)
43 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
44 * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL)
45 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
46 * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL)
47 *
48 * from: @(#)locore.s 8.5 (Berkeley) 1/4/94
49 * JNPR: swtch.S,v 1.6.2.1 2007/09/10 10:36:50 girish
50 * $FreeBSD: releng/10.0/sys/mips/mips/swtch.S 249901 2013-04-25 17:23:54Z imp $
51 */
52
53 /*
54 * Contains code that is the first executed at boot time plus
55 * assembly language support routines.
56 */
57
58 #include "opt_compat.h"
59 #include <sys/syscall.h>
60 #include <machine/asm.h>
61 #include <machine/cpu.h>
62 #include <machine/cpuregs.h>
63 #include <machine/regnum.h>
64 #include <machine/pte.h>
65 #include <machine/pcb.h>
66
67 #include "assym.s"
68
69 .set noreorder # Noreorder is default style!
70
71 #define SAVE_U_PCB_REG(reg, offs, base) \
72 REG_S reg, U_PCB_REGS + (SZREG * offs) (base)
73
74 #define RESTORE_U_PCB_REG(reg, offs, base) \
75 REG_L reg, U_PCB_REGS + (SZREG * offs) (base)
76
77 #define SAVE_U_PCB_FPREG(reg, offs, base) \
78 FP_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
79
80 #define RESTORE_U_PCB_FPREG(reg, offs, base) \
81 FP_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
82
83 #define SAVE_U_PCB_FPSR(reg, offs, base) \
84 REG_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
85
86 #define RESTORE_U_PCB_FPSR(reg, offs, base) \
87 REG_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
88
89 #define SAVE_U_PCB_CONTEXT(reg, offs, base) \
90 REG_S reg, U_PCB_CONTEXT + (SZREG * offs) (base)
91
92 #define RESTORE_U_PCB_CONTEXT(reg, offs, base) \
93 REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base)
94
95
96 /*
97 * Setup for and return to user.
98 */
99 LEAF(fork_trampoline)
100 move a0,s0
101 move a1,s1
102 jal _C_LABEL(fork_exit)
103 move a2,s2 #BDSlot
104
105 DO_AST
106
107 mfc0 v0, MIPS_COP_0_STATUS
108 and v0, ~(MIPS_SR_INT_IE)
109 mtc0 v0, MIPS_COP_0_STATUS # disable interrupts
110 COP0_SYNC
111 /*
112 * The use of k1 for storing the PCB pointer must be done only
113 * after interrupts are disabled. Otherwise it will get overwritten
114 * by the interrupt code.
115 */
116 .set noat
117 GET_CPU_PCPU(k1)
118 PTR_L k1, PC_CURPCB(k1)
119
120 RESTORE_U_PCB_REG(t0, MULLO, k1)
121 RESTORE_U_PCB_REG(t1, MULHI, k1)
122 mtlo t0
123 mthi t1
124 RESTORE_U_PCB_REG(a0, PC, k1)
125 RESTORE_U_PCB_REG(AT, AST, k1)
126 RESTORE_U_PCB_REG(v0, V0, k1)
127 MTC0 a0, MIPS_COP_0_EXC_PC # set return address
128
129 RESTORE_U_PCB_REG(v1, V1, k1)
130 RESTORE_U_PCB_REG(a0, A0, k1)
131 RESTORE_U_PCB_REG(a1, A1, k1)
132 RESTORE_U_PCB_REG(a2, A2, k1)
133 RESTORE_U_PCB_REG(a3, A3, k1)
134 RESTORE_U_PCB_REG(t0, T0, k1)
135 RESTORE_U_PCB_REG(t1, T1, k1)
136 RESTORE_U_PCB_REG(t2, T2, k1)
137 RESTORE_U_PCB_REG(t3, T3, k1)
138 RESTORE_U_PCB_REG(ta0, TA0, k1)
139 RESTORE_U_PCB_REG(ta1, TA1, k1)
140 RESTORE_U_PCB_REG(ta2, TA2, k1)
141 RESTORE_U_PCB_REG(ta3, TA3, k1)
142 RESTORE_U_PCB_REG(s0, S0, k1)
143 RESTORE_U_PCB_REG(s1, S1, k1)
144 RESTORE_U_PCB_REG(s2, S2, k1)
145 RESTORE_U_PCB_REG(s3, S3, k1)
146 RESTORE_U_PCB_REG(s4, S4, k1)
147 RESTORE_U_PCB_REG(s5, S5, k1)
148 RESTORE_U_PCB_REG(s6, S6, k1)
149 RESTORE_U_PCB_REG(s7, S7, k1)
150 RESTORE_U_PCB_REG(t8, T8, k1)
151 RESTORE_U_PCB_REG(t9, T9, k1)
152 RESTORE_U_PCB_REG(k0, SR, k1)
153 RESTORE_U_PCB_REG(gp, GP, k1)
154 RESTORE_U_PCB_REG(s8, S8, k1)
155 RESTORE_U_PCB_REG(ra, RA, k1)
156 RESTORE_U_PCB_REG(sp, SP, k1)
157 li k1, ~MIPS_SR_INT_MASK
158 and k0, k0, k1
159 mfc0 k1, MIPS_COP_0_STATUS
160 and k1, k1, MIPS_SR_INT_MASK
161 or k0, k0, k1
162 mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...)
163 HAZARD_DELAY
164 sync
165 eret
166 .set at
167 END(fork_trampoline)
168
169 /*
170 * Update pcb, saving current processor state.
171 * Note: this only works if pcbp != curproc's pcb since
172 * cpu_switch() will copy over pcb_context.
173 *
174 * savectx(struct pcb *pcbp);
175 */
176 LEAF(savectx)
177 SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
178 SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
179 SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
180 SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
181 mfc0 v0, MIPS_COP_0_STATUS
182 SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
183 SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
184 SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
185 SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
186 SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0)
187 SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
188 SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
189 SAVE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0)
190 SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
191
192 move v0, ra /* save 'ra' before we trash it */
193 jal 1f
194 nop
195 1:
196 SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0)
197 move ra, v0 /* restore 'ra' before returning */
198
199 j ra
200 move v0, zero
201 END(savectx)
202
203 NON_LEAF(cpu_throw, CALLFRAME_SIZ, ra)
204 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
205 nop
206 nop
207 and a3, t0, ~(MIPS_SR_INT_IE)
208 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
209 ITLBNOPFIX
210 j mips_sw1 # We're not interested in old
211 # thread's context, so jump
212 # right to action
213 nop # BDSLOT
214 END(cpu_throw)
215
216 /*
217 * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx);
218 * a0 - old
219 * a1 - new
220 * a2 - mtx
221 * Find the highest priority process and resume it.
222 */
223 NON_LEAF(cpu_switch, CALLFRAME_SIZ, ra)
224 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
225 nop
226 nop
227 and a3, t0, ~(MIPS_SR_INT_IE)
228 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
229 ITLBNOPFIX
230 beqz a0, mips_sw1
231 move a3, a0
232 PTR_L a0, TD_PCB(a0) # load PCB addr of curproc
233 SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0) # save old sp
234 PTR_SUBU sp, sp, CALLFRAME_SIZ
235 REG_S ra, CALLFRAME_RA(sp)
236 .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
237 SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0) # do a 'savectx()'
238 SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
239 SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
240 SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
241 SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
242 SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
243 SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
244 SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
245 SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
246 SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0) # save return address
247 SAVE_U_PCB_CONTEXT(t0, PCB_REG_SR, a0) # save status register
248 SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
249 jal getpc
250 nop
251 getpc:
252 SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0) # save return address
253
254 #ifdef CPU_CNMIPS
255
256 lw t2, TD_MDFLAGS(a3) # get md_flags
257 and t1, t2, MDTD_COP2USED
258 beqz t1, cop2_untouched
259 nop
260
261 /* Clear cop2used flag */
262 and t2, t2, ~MDTD_COP2USED
263 sw t2, TD_MDFLAGS(a3)
264
265 and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit
266 SAVE_U_PCB_CONTEXT(t2, PCB_REG_SR, a0) # save status register
267
268 RESTORE_U_PCB_REG(t0, PS, a0) # get CPU status register
269 and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit
270 SAVE_U_PCB_REG(t2, PS, a0) # save stratus register
271
272 /* preserve a0..a3 */
273 move s0, a0
274 move s1, a1
275 move s2, a2
276 move s3, a3
277
278 /* does kernel own COP2 context? */
279 lw t1, TD_COP2OWNER(a3) # get md_cop2owner
280 beqz t1, userland_cop2 # 0 - it's userland context
281 nop
282
283 PTR_L a0, TD_COP2(a3)
284 beqz a0, no_cop2_context
285 nop
286
287 j do_cop2_save
288 nop
289
290 userland_cop2:
291
292 PTR_L a0, TD_UCOP2(a3)
293 beqz a0, no_cop2_context
294 nop
295
296 do_cop2_save:
297 jal octeon_cop2_save
298 nop
299
300 no_cop2_context:
301 move a3, s3
302 move a2, s2
303 move a1, s1
304 move a0, s0
305
306 cop2_untouched:
307 #endif
308
309 PTR_S a2, TD_LOCK(a3) # Switchout td_lock
310
311 mips_sw1:
312 #if defined(SMP) && defined(SCHED_ULE)
313 PTR_LA t0, _C_LABEL(blocked_lock)
314 blocked_loop:
315 PTR_L t1, TD_LOCK(a1)
316 beq t0, t1, blocked_loop
317 nop
318 #endif
319 move s7, a1 # Store newthread
320 /*
321 * Switch to new context.
322 */
323 GET_CPU_PCPU(a3)
324 PTR_S a1, PC_CURTHREAD(a3)
325 PTR_L a2, TD_PCB(a1)
326 PTR_S a2, PC_CURPCB(a3)
327 PTR_L v0, TD_KSTACK(a1)
328 #if defined(__mips_n64)
329 PTR_LI s0, MIPS_XKSEG_START
330 #else
331 PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2,
332 #endif
333 bltu v0, s0, sw2 # no need to insert in TLB.
334 PTE_L a1, TD_UPTE + 0(s7) # a1 = u. pte #0
335 PTE_L a2, TD_UPTE + PTESIZE(s7) # a2 = u. pte #1
336 /*
337 * Wiredown the USPACE of newproc in TLB entry#0. Check whether target
338 * USPACE is already in another place of TLB before that, and if so
339 * invalidate that TLB entry.
340 * NOTE: This is hard coded to UPAGES == 2.
341 * Also, there should be no TLB faults at this point.
342 */
343 MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va
344 HAZARD_DELAY
345 tlbp # probe VPN
346 HAZARD_DELAY
347 mfc0 s0, MIPS_COP_0_TLB_INDEX
348 HAZARD_DELAY
349
350 PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry
351 bltz s0, entry0set
352 nop
353 sll s0, PAGE_SHIFT + 1
354 addu t1, s0
355 MTC0 t1, MIPS_COP_0_TLB_HI
356 PTE_MTC0 zero, MIPS_COP_0_TLB_LO0
357 PTE_MTC0 zero, MIPS_COP_0_TLB_LO1
358 HAZARD_DELAY
359 tlbwi
360 HAZARD_DELAY
361 MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again
362
363 entry0set:
364 /* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */
365 mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0
366 HAZARD_DELAY
367 PTE_MTC0 a1, MIPS_COP_0_TLB_LO0 # upte[0]
368 HAZARD_DELAY
369 PTE_MTC0 a2, MIPS_COP_0_TLB_LO1 # upte[1]
370 HAZARD_DELAY
371 tlbwi # set TLB entry #0
372 HAZARD_DELAY
373 /*
374 * Now running on new u struct.
375 */
376 sw2:
377 PTR_L s0, TD_PCB(s7)
378 RESTORE_U_PCB_CONTEXT(sp, PCB_REG_SP, s0)
379 PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer
380 jalr t1 # s7 = new proc pointer
381 move a0, s7 # BDSLOT
382 /*
383 * Restore registers and return.
384 */
385 move a0, s0
386 RESTORE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
387 RESTORE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0) # restore kernel context
388 RESTORE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
389 RESTORE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
390 RESTORE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
391 RESTORE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
392 RESTORE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
393 RESTORE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
394 RESTORE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
395 RESTORE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
396 RESTORE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
397 RESTORE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
398
399 mfc0 t0, MIPS_COP_0_STATUS
400 and t0, t0, MIPS_SR_INT_MASK
401 and v0, v0, ~MIPS_SR_INT_MASK
402 or v0, v0, t0
403 mtc0 v0, MIPS_COP_0_STATUS
404 ITLBNOPFIX
405
406 j ra
407 nop
408 END(cpu_switch)
409
410 /*----------------------------------------------------------------------------
411 *
412 * MipsSwitchFPState --
413 *
414 * Save the current state into 'from' and restore it from 'to'.
415 *
416 * MipsSwitchFPState(from, to)
417 * struct thread *from;
418 * struct trapframe *to;
419 *
420 * Results:
421 * None.
422 *
423 * Side effects:
424 * None.
425 *
426 *----------------------------------------------------------------------------
427 */
428 LEAF(MipsSwitchFPState)
429 mfc0 t1, MIPS_COP_0_STATUS # Save old SR
430 li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
431 mtc0 t0, MIPS_COP_0_STATUS
432 ITLBNOPFIX
433
434 beq a0, zero, 1f # skip save if NULL pointer
435 nop
436 /*
437 * First read out the status register to make sure that all FP operations
438 * have completed.
439 */
440 PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc
441 cfc1 t0, MIPS_FPU_CSR # stall til FP done
442 cfc1 t0, MIPS_FPU_CSR # now get status
443 li t3, ~MIPS_SR_COP_1_BIT
444 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
445 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
446 and t2, t2, t3 # clear COP_1 enable bit
447 SAVE_U_PCB_REG(t2, PS, a0) # save new status register
448 /*
449 * Save the floating point registers.
450 */
451 SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
452 SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
453 SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
454 SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
455 SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
456 SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
457 SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
458 SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
459 SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
460 SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
461 SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
462 SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
463 SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
464 SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
465 SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
466 SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
467 SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
468 SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
469 SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
470 SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
471 SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
472 SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
473 SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
474 SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
475 SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
476 SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
477 SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
478 SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
479 SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
480 SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
481 SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
482 SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
483
484 1:
485 /*
486 * Restore the floating point registers.
487 */
488 RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register
489 RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
490 RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
491 RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
492 RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
493 RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
494 RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
495 RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
496 RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
497 RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
498 RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
499 RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
500 RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
501 RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
502 RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
503 RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
504 RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
505 RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
506 RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
507 RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
508 RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
509 RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
510 RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
511 RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
512 RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
513 RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
514 RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
515 RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
516 RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
517 RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
518 RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
519 RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
520 RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
521
522 and t0, t0, ~MIPS_FPU_EXCEPTION_BITS
523 ctc1 t0, MIPS_FPU_CSR
524 nop
525
526 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
527 ITLBNOPFIX
528 j ra
529 nop
530 END(MipsSwitchFPState)
531
532 /*----------------------------------------------------------------------------
533 *
534 * MipsSaveCurFPState --
535 *
536 * Save the current floating point coprocessor state.
537 *
538 * MipsSaveCurFPState(td)
539 * struct thread *td;
540 *
541 * Results:
542 * None.
543 *
544 * Side effects:
545 * machFPCurProcPtr is cleared.
546 *
547 *----------------------------------------------------------------------------
548 */
549 LEAF(MipsSaveCurFPState)
550 PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread
551 mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and
552 li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
553 mtc0 t0, MIPS_COP_0_STATUS
554 ITLBNOPFIX
555 GET_CPU_PCPU(a1)
556 PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved
557 /*
558 * First read out the status register to make sure that all FP operations
559 * have completed.
560 */
561 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
562 li t3, ~MIPS_SR_COP_1_BIT
563 and t2, t2, t3 # clear COP_1 enable bit
564 cfc1 t0, MIPS_FPU_CSR # stall til FP done
565 cfc1 t0, MIPS_FPU_CSR # now get status
566 SAVE_U_PCB_REG(t2, PS, a0) # save new status register
567 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
568 /*
569 * Save the floating point registers.
570 */
571 SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
572 SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
573 SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
574 SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
575 SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
576 SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
577 SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
578 SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
579 SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
580 SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
581 SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
582 SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
583 SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
584 SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
585 SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
586 SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
587 SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
588 SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
589 SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
590 SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
591 SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
592 SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
593 SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
594 SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
595 SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
596 SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
597 SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
598 SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
599 SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
600 SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
601 SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
602 SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
603
604 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
605 ITLBNOPFIX
606 j ra
607 nop
608 END(MipsSaveCurFPState)
609
610 /*
611 * This code is copied the user's stack for returning from signal handlers
612 * (see sendsig() and sigreturn()). We have to compute the address
613 * of the sigcontext struct for the sigreturn call.
614 */
615 .globl _C_LABEL(sigcode)
616 _C_LABEL(sigcode):
617 PTR_ADDU a0, sp, SIGF_UC # address of ucontext
618 li v0, SYS_sigreturn
619 # sigreturn (ucp)
620 syscall
621 break 0 # just in case sigreturn fails
622 .globl _C_LABEL(esigcode)
623 _C_LABEL(esigcode):
624
625 .data
626 .globl szsigcode
627 szsigcode:
628 .long esigcode-sigcode
629 .text
630
631 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
632 .globl _C_LABEL(sigcode32)
633 _C_LABEL(sigcode32):
634 addu a0, sp, SIGF32_UC # address of ucontext
635 li v0, SYS_sigreturn
636 # sigreturn (ucp)
637 syscall
638 break 0 # just in case sigreturn fails
639 .globl _C_LABEL(esigcode32)
640 _C_LABEL(esigcode32):
641
642 .data
643 .globl szsigcode32
644 szsigcode32:
645 .long esigcode32-sigcode32
646 .text
647 #endif
Cache object: 0969cc94f8ba43bcadb21dbb3e35d6d4
|