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 * 3. 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/12.0/sys/mips/mips/swtch.S 332122 2018-04-06 17:35:35Z brooks $
51 */
52
53 /*
54 * Contains code that is the first executed at boot time plus
55 * assembly language support routines.
56 */
57
58 #include <sys/syscall.h>
59 #include <machine/asm.h>
60 #include <machine/cpu.h>
61 #include <machine/cpuregs.h>
62 #include <machine/regnum.h>
63 #include <machine/pte.h>
64 #include <machine/pcb.h>
65
66 #include "assym.inc"
67
68 .set noreorder # Noreorder is default style!
69
70 /*
71 * Setup for and return to user.
72 */
73 LEAF(fork_trampoline)
74 move a0,s0
75 move a1,s1
76 jal _C_LABEL(fork_exit)
77 move a2,s2 #BDSlot
78
79 DO_AST
80
81 mfc0 v0, MIPS_COP_0_STATUS
82 and v0, ~(MIPS_SR_INT_IE)
83 mtc0 v0, MIPS_COP_0_STATUS # disable interrupts
84 COP0_SYNC
85 /*
86 * The use of k1 for storing the PCB pointer must be done only
87 * after interrupts are disabled. Otherwise it will get overwritten
88 * by the interrupt code.
89 */
90 .set noat
91 GET_CPU_PCPU(k1)
92 PTR_L k1, PC_CURPCB(k1)
93
94 RESTORE_U_PCB_REG(t0, MULLO, k1)
95 RESTORE_U_PCB_REG(t1, MULHI, k1)
96 mtlo t0
97 mthi t1
98 RESTORE_U_PCB_REG(a0, PC, k1)
99 RESTORE_U_PCB_REG(AT, AST, k1)
100 RESTORE_U_PCB_REG(v0, V0, k1)
101 MTC0 a0, MIPS_COP_0_EXC_PC # set return address
102
103 RESTORE_U_PCB_REG(v1, V1, k1)
104 RESTORE_U_PCB_REG(a0, A0, k1)
105 RESTORE_U_PCB_REG(a1, A1, k1)
106 RESTORE_U_PCB_REG(a2, A2, k1)
107 RESTORE_U_PCB_REG(a3, A3, k1)
108 RESTORE_U_PCB_REG(t0, T0, k1)
109 RESTORE_U_PCB_REG(t1, T1, k1)
110 RESTORE_U_PCB_REG(t2, T2, k1)
111 RESTORE_U_PCB_REG(t3, T3, k1)
112 RESTORE_U_PCB_REG(ta0, TA0, k1)
113 RESTORE_U_PCB_REG(ta1, TA1, k1)
114 RESTORE_U_PCB_REG(ta2, TA2, k1)
115 RESTORE_U_PCB_REG(ta3, TA3, k1)
116 RESTORE_U_PCB_REG(s0, S0, k1)
117 RESTORE_U_PCB_REG(s1, S1, k1)
118 RESTORE_U_PCB_REG(s2, S2, k1)
119 RESTORE_U_PCB_REG(s3, S3, k1)
120 RESTORE_U_PCB_REG(s4, S4, k1)
121 RESTORE_U_PCB_REG(s5, S5, k1)
122 RESTORE_U_PCB_REG(s6, S6, k1)
123 RESTORE_U_PCB_REG(s7, S7, k1)
124 RESTORE_U_PCB_REG(t8, T8, k1)
125 RESTORE_U_PCB_REG(t9, T9, k1)
126 RESTORE_U_PCB_REG(k0, SR, k1)
127 RESTORE_U_PCB_REG(gp, GP, k1)
128 RESTORE_U_PCB_REG(s8, S8, k1)
129 RESTORE_U_PCB_REG(ra, RA, k1)
130 RESTORE_U_PCB_REG(sp, SP, k1)
131 li k1, ~MIPS_SR_INT_MASK
132 and k0, k0, k1
133 mfc0 k1, MIPS_COP_0_STATUS
134 and k1, k1, MIPS_SR_INT_MASK
135 or k0, k0, k1
136 mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...)
137 HAZARD_DELAY
138 sync
139 eret
140 .set at
141 END(fork_trampoline)
142
143 /*
144 * Update pcb, saving current processor state.
145 * Note: this only works if pcbp != curproc's pcb since
146 * cpu_switch() will copy over pcb_context.
147 *
148 * savectx(struct pcb *pcbp);
149 */
150 LEAF(savectx)
151 SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
152 SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
153 SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
154 SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
155 mfc0 v0, MIPS_COP_0_STATUS
156 SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
157 SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
158 SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
159 SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
160 SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0)
161 SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
162 SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
163 SAVE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0)
164 SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
165
166 move v0, ra /* save 'ra' before we trash it */
167 jal 1f
168 nop
169 1:
170 SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0)
171 move ra, v0 /* restore 'ra' before returning */
172
173 j ra
174 move v0, zero
175 END(savectx)
176
177 NESTED(cpu_throw, CALLFRAME_SIZ, ra)
178 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
179 nop
180 nop
181 and a3, t0, ~(MIPS_SR_INT_IE)
182 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
183 ITLBNOPFIX
184 j mips_sw1 # We're not interested in old
185 # thread's context, so jump
186 # right to action
187 nop # BDSLOT
188 END(cpu_throw)
189
190 /*
191 * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx);
192 * a0 - old
193 * a1 - new
194 * a2 - mtx
195 * Find the highest priority process and resume it.
196 */
197 NESTED(cpu_switch, CALLFRAME_SIZ, ra)
198 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
199 nop
200 nop
201 and a3, t0, ~(MIPS_SR_INT_IE)
202 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
203 ITLBNOPFIX
204 beqz a0, mips_sw1
205 move a3, a0
206 PTR_L a0, TD_PCB(a0) # load PCB addr of curproc
207 SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0) # save old sp
208 PTR_SUBU sp, sp, CALLFRAME_SIZ
209 REG_S ra, CALLFRAME_RA(sp)
210 .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
211 SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0) # do a 'savectx()'
212 SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
213 SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
214 SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
215 SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
216 SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
217 SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
218 SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
219 SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
220 SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0) # save return address
221 SAVE_U_PCB_CONTEXT(t0, PCB_REG_SR, a0) # save status register
222 SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
223 jal getpc
224 nop
225 getpc:
226 SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0) # save return address
227
228 #ifdef CPU_CNMIPS
229
230 lw t2, TD_MDFLAGS(a3) # get md_flags
231 and t1, t2, MDTD_COP2USED
232 beqz t1, cop2_untouched
233 nop
234
235 /* Clear cop2used flag */
236 and t2, t2, ~MDTD_COP2USED
237 sw t2, TD_MDFLAGS(a3)
238
239 and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit
240 SAVE_U_PCB_CONTEXT(t2, PCB_REG_SR, a0) # save status register
241
242 RESTORE_U_PCB_REG(t0, PS, a0) # get CPU status register
243 and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit
244 SAVE_U_PCB_REG(t2, PS, a0) # save stratus register
245
246 /* preserve a0..a3 */
247 move s0, a0
248 move s1, a1
249 move s2, a2
250 move s3, a3
251
252 /* does kernel own COP2 context? */
253 lw t1, TD_COP2OWNER(a3) # get md_cop2owner
254 beqz t1, userland_cop2 # 0 - it's userland context
255 nop
256
257 PTR_L a0, TD_COP2(a3)
258 beqz a0, no_cop2_context
259 nop
260
261 j do_cop2_save
262 nop
263
264 userland_cop2:
265
266 PTR_L a0, TD_UCOP2(a3)
267 beqz a0, no_cop2_context
268 nop
269
270 do_cop2_save:
271 jal octeon_cop2_save
272 nop
273
274 no_cop2_context:
275 move a3, s3
276 move a2, s2
277 move a1, s1
278 move a0, s0
279
280 cop2_untouched:
281 #endif
282
283 PTR_S a2, TD_LOCK(a3) # Switchout td_lock
284
285 mips_sw1:
286 #if defined(SMP) && defined(SCHED_ULE)
287 PTR_LA t0, _C_LABEL(blocked_lock)
288 blocked_loop:
289 PTR_L t1, TD_LOCK(a1)
290 beq t0, t1, blocked_loop
291 nop
292 #endif
293 move s7, a1 # Store newthread
294 /*
295 * Switch to new context.
296 */
297 GET_CPU_PCPU(a3)
298 PTR_S a1, PC_CURTHREAD(a3)
299 PTR_L a2, TD_PCB(a1)
300 PTR_S a2, PC_CURPCB(a3)
301 PTR_L v0, TD_KSTACK(a1)
302 #if defined(__mips_n64)
303 PTR_LI s0, MIPS_XKSEG_START
304 #else
305 PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2,
306 #endif
307 bltu v0, s0, sw2 # no need to insert in TLB.
308 PTE_L a1, TD_UPTE + 0(s7) # a1 = u. pte #0
309 PTE_L a2, TD_UPTE + PTESIZE(s7) # a2 = u. pte #1
310 /*
311 * Wiredown the USPACE of newproc in TLB entry#0. Check whether target
312 * USPACE is already in another place of TLB before that, and if so
313 * invalidate that TLB entry.
314 * NOTE: This is hard coded to UPAGES == 2.
315 * Also, there should be no TLB faults at this point.
316 */
317 MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va
318 HAZARD_DELAY
319 tlbp # probe VPN
320 HAZARD_DELAY
321 mfc0 s0, MIPS_COP_0_TLB_INDEX
322 HAZARD_DELAY
323
324 PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry
325 bltz s0, entry0set
326 nop
327 sll s0, PAGE_SHIFT + 1
328 addu t1, s0
329 MTC0 t1, MIPS_COP_0_TLB_HI
330 PTE_MTC0 zero, MIPS_COP_0_TLB_LO0
331 PTE_MTC0 zero, MIPS_COP_0_TLB_LO1
332 HAZARD_DELAY
333 tlbwi
334 HAZARD_DELAY
335 MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again
336
337 entry0set:
338 /* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */
339 mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0
340 HAZARD_DELAY
341 PTE_MTC0 a1, MIPS_COP_0_TLB_LO0 # upte[0]
342 HAZARD_DELAY
343 PTE_MTC0 a2, MIPS_COP_0_TLB_LO1 # upte[1]
344 HAZARD_DELAY
345 tlbwi # set TLB entry #0
346 HAZARD_DELAY
347 /*
348 * Now running on new u struct.
349 */
350 sw2:
351 PTR_L s0, TD_PCB(s7)
352 RESTORE_U_PCB_CONTEXT(sp, PCB_REG_SP, s0)
353 PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer
354 jalr t1 # s7 = new proc pointer
355 move a0, s7 # BDSLOT
356 /*
357 * Restore registers and return.
358 */
359 move a0, s0
360 move a1, s7
361 RESTORE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
362 RESTORE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0) # restore kernel context
363 RESTORE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
364 RESTORE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
365 RESTORE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
366 RESTORE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
367 RESTORE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
368 RESTORE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
369 RESTORE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
370 RESTORE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
371 RESTORE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
372 RESTORE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
373
374 mfc0 t0, MIPS_COP_0_STATUS
375 and t0, t0, MIPS_SR_INT_MASK
376 and v0, v0, ~MIPS_SR_INT_MASK
377 or v0, v0, t0
378 mtc0 v0, MIPS_COP_0_STATUS
379 ITLBNOPFIX
380 /*
381 * Set the new thread's TLS pointer.
382 *
383 * Note that this code is removed if the CPU doesn't support ULRI by
384 * remove_userlocal_code() in cpu.c.
385 */
386 PTR_L t0, TD_MDTLS(a1) # Get TLS pointer
387 PTR_L t1, TD_MDTLS_TCB_OFFSET(a1) # Get TLS/TCB offset
388 PTR_ADDU v0, t0, t1
389 MTC0 v0, MIPS_COP_0_USERLOCAL, 2 # write it to ULR for rdhwr
390
391 j ra
392 nop
393 END(cpu_switch)
394
395 /*----------------------------------------------------------------------------
396 *
397 * MipsSwitchFPState --
398 *
399 * Save the current state into 'from' and restore it from 'to'.
400 *
401 * MipsSwitchFPState(from, to)
402 * struct thread *from;
403 * struct trapframe *to;
404 *
405 * Results:
406 * None.
407 *
408 * Side effects:
409 * None.
410 *
411 *----------------------------------------------------------------------------
412 */
413 LEAF(MipsSwitchFPState)
414 .set push
415 .set hardfloat
416 mfc0 t1, MIPS_COP_0_STATUS # Save old SR
417 HAZARD_DELAY
418 #if defined(__mips_n32) || defined(__mips_n64)
419 or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR # enable the coprocessor
420 #else
421 or t0, t1, MIPS_SR_COP_1_BIT # enable the coprocessor
422 #endif
423 mtc0 t0, MIPS_COP_0_STATUS
424 HAZARD_DELAY
425 ITLBNOPFIX
426
427 beq a0, zero, 1f # skip save if NULL pointer
428 nop
429 /*
430 * First read out the status register to make sure that all FP operations
431 * have completed.
432 */
433 PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc
434 cfc1 t0, MIPS_FPU_CSR # stall til FP done
435 cfc1 t0, MIPS_FPU_CSR # now get status
436 li t3, ~MIPS_SR_COP_1_BIT
437 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
438 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
439 and t2, t2, t3 # clear COP_1 enable bit
440 SAVE_U_PCB_REG(t2, PS, a0) # save new status register
441 /*
442 * Save the floating point registers.
443 */
444 SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
445 SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
446 SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
447 SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
448 SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
449 SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
450 SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
451 SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
452 SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
453 SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
454 SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
455 SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
456 SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
457 SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
458 SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
459 SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
460 SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
461 SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
462 SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
463 SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
464 SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
465 SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
466 SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
467 SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
468 SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
469 SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
470 SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
471 SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
472 SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
473 SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
474 SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
475 SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
476
477 1:
478 /*
479 * Restore the floating point registers.
480 */
481 RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register
482 RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
483 RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
484 RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
485 RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
486 RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
487 RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
488 RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
489 RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
490 RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
491 RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
492 RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
493 RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
494 RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
495 RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
496 RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
497 RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
498 RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
499 RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
500 RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
501 RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
502 RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
503 RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
504 RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
505 RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
506 RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
507 RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
508 RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
509 RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
510 RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
511 RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
512 RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
513 RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
514
515 and t0, t0, ~MIPS_FPU_EXCEPTION_BITS
516 ctc1 t0, MIPS_FPU_CSR
517 nop
518
519 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
520 ITLBNOPFIX
521 j ra
522 nop
523 .set pop
524 END(MipsSwitchFPState)
525
526 /*----------------------------------------------------------------------------
527 *
528 * MipsFPID --
529 *
530 * Read and return the floating point implementation register.
531 *
532 * uint32_t
533 * MipsFPID(void)
534 *
535 * Results:
536 * Floating point implementation register.
537 *
538 * Side effects:
539 * None.
540 *
541 *----------------------------------------------------------------------------
542 */
543 LEAF(MipsFPID)
544 .set push
545 .set hardfloat
546 mfc0 t1, MIPS_COP_0_STATUS # Save the status register.
547 HAZARD_DELAY
548 #if defined(__mips_n32) || defined(__mips_n64)
549 or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR
550 #else
551 or t0, t1, MIPS_SR_COP_1_BIT
552 #endif
553 mtc0 t0, MIPS_COP_0_STATUS # Enable the coprocessor
554 HAZARD_DELAY
555 ITLBNOPFIX
556 cfc1 v0, MIPS_FPU_ID
557 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
558 ITLBNOPFIX
559 j ra
560 nop
561 .set pop
562 END(MipsFPID)
563
564 /*----------------------------------------------------------------------------
565 *
566 * MipsSaveCurFPState --
567 *
568 * Save the current floating point coprocessor state.
569 *
570 * MipsSaveCurFPState(td)
571 * struct thread *td;
572 *
573 * Results:
574 * None.
575 *
576 * Side effects:
577 * machFPCurProcPtr is cleared.
578 *
579 *----------------------------------------------------------------------------
580 */
581 LEAF(MipsSaveCurFPState)
582 .set push
583 .set hardfloat
584 PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread
585 mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and
586 HAZARD_DELAY
587 #if defined(__mips_n32) || defined(__mips_n64)
588 or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR # enable the coprocessor
589 #else
590 or t0, t1, MIPS_SR_COP_1_BIT # enable the coprocessor
591 #endif
592 mtc0 t0, MIPS_COP_0_STATUS
593 HAZARD_DELAY
594 ITLBNOPFIX
595 GET_CPU_PCPU(a1)
596 PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved
597 /*
598 * First read out the status register to make sure that all FP operations
599 * have completed.
600 */
601 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
602 li t3, ~MIPS_SR_COP_1_BIT
603 and t2, t2, t3 # clear COP_1 enable bit
604 cfc1 t0, MIPS_FPU_CSR # stall til FP done
605 cfc1 t0, MIPS_FPU_CSR # now get status
606 SAVE_U_PCB_REG(t2, PS, a0) # save new status register
607 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
608 /*
609 * Save the floating point registers.
610 */
611 SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
612 SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
613 SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
614 SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
615 SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
616 SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
617 SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
618 SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
619 SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
620 SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
621 SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
622 SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
623 SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
624 SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
625 SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
626 SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
627 SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
628 SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
629 SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
630 SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
631 SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
632 SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
633 SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
634 SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
635 SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
636 SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
637 SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
638 SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
639 SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
640 SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
641 SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
642 SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
643
644 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
645 ITLBNOPFIX
646 j ra
647 nop
648 .set pop
649 END(MipsSaveCurFPState)
650
651 /*
652 * This code is copied the user's stack for returning from signal handlers
653 * (see sendsig() and sigreturn()). We have to compute the address
654 * of the sigcontext struct for the sigreturn call.
655 */
656 .globl _C_LABEL(sigcode)
657 _C_LABEL(sigcode):
658 PTR_ADDU a0, sp, SIGF_UC # address of ucontext
659 li v0, SYS_sigreturn
660 # sigreturn (ucp)
661 syscall
662 break 0 # just in case sigreturn fails
663 .globl _C_LABEL(esigcode)
664 _C_LABEL(esigcode):
665
666 .data
667 .globl szsigcode
668 szsigcode:
669 .long esigcode-sigcode
670 .text
671
672 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
673 .globl _C_LABEL(sigcode32)
674 _C_LABEL(sigcode32):
675 addu a0, sp, SIGF32_UC # address of ucontext
676 li v0, SYS_sigreturn
677 # sigreturn (ucp)
678 syscall
679 break 0 # just in case sigreturn fails
680 .globl _C_LABEL(esigcode32)
681 _C_LABEL(esigcode32):
682
683 .data
684 .globl szsigcode32
685 szsigcode32:
686 .long esigcode32-sigcode32
687 .text
688 #endif
Cache object: 15eef0e3dcea117d4c224a5555706af4
|