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/8.0/sys/mips/mips/swtch.S 178172 2008-04-13 07:27:37Z 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_cputype.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
66 #include "assym.s"
67
68 #if defined(ISA_MIPS32)
69 #undef WITH_64BIT_CP0
70 #elif defined(ISA_MIPS64)
71 #define WITH_64BIT_CP0
72 #elif defined(ISA_MIPS3)
73 #define WITH_64BIT_CP0
74 #else
75 #error "Please write the code for this ISA"
76 #endif
77
78 #ifdef WITH_64BIT_CP0
79 #define _SLL dsll
80 #define _SRL dsrl
81 #define _MFC0 dmfc0
82 #define _MTC0 dmtc0
83 #define WIRED_SHIFT 34
84 #define PAGE_SHIFT 34
85 #else
86 #define _SLL sll
87 #define _SRL srl
88 #define _MFC0 mfc0
89 #define _MTC0 mtc0
90 #define WIRED_SHIFT 2
91 #define PAGE_SHIFT 2
92 #endif
93 .set noreorder # Noreorder is default style!
94 #if defined(ISA_MIPS32)
95 .set mips32
96 #elif defined(ISA_MIPS64)
97 .set mips64
98 #elif defined(ISA_MIPS3)
99 .set mips3
100 #endif
101
102 #if defined(ISA_MIPS32)
103 #define STORE sw /* 32 bit mode regsave instruction */
104 #define LOAD lw /* 32 bit mode regload instruction */
105 #define RSIZE 4 /* 32 bit mode register size */
106 #define STORE_FP swc1 /* 32 bit mode fp regsave instruction */
107 #define LOAD_FP lwc1 /* 32 bit mode fp regload instruction */
108 #define FP_RSIZE 4 /* 32 bit mode fp register size */
109 #else
110 #define STORE sd /* 64 bit mode regsave instruction */
111 #define LOAD ld /* 64 bit mode regload instruction */
112 #define RSIZE 8 /* 64 bit mode register size */
113 #define STORE_FP sdc1 /* 64 bit mode fp regsave instruction */
114 #define LOAD_FP ldc1 /* 64 bit mode fp regload instruction */
115 #define FP_RSIZE 8 /* 64 bit mode fp register size */
116 #endif
117
118 /*
119 * FREEBSD_DEVELOPERS_FIXME
120 * Some MIPS CPU may need delays using nops between executing CP0 Instructions
121 */
122
123 #if 1
124 #define HAZARD_DELAY nop ; nop ; nop ; nop
125 #else
126 #define HAZARD_DELAY
127 #endif
128
129 #define SAVE_U_PCB_REG(reg, offs, base) \
130 STORE reg, U_PCB_REGS + (RSIZE * offs) (base)
131
132 #define RESTORE_U_PCB_REG(reg, offs, base) \
133 LOAD reg, U_PCB_REGS + (RSIZE * offs) (base)
134
135 #define SAVE_U_PCB_FPREG(reg, offs, base) \
136 STORE_FP reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
137
138 #define RESTORE_U_PCB_FPREG(reg, offs, base) \
139 LOAD_FP reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
140
141 #define SAVE_U_PCB_FPSR(reg, offs, base) \
142 STORE reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
143
144 #define RESTORE_U_PCB_FPSR(reg, offs, base) \
145 LOAD reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
146
147 #define SAVE_U_PCB_CONTEXT(reg, offs, base) \
148 STORE reg, U_PCB_CONTEXT + (RSIZE * offs) (base)
149
150 #define RESTORE_U_PCB_CONTEXT(reg, offs, base) \
151 LOAD reg, U_PCB_CONTEXT + (RSIZE * offs) (base)
152
153 #define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
154
155 /*
156 * Setup for and return to user.
157 */
158 LEAF(fork_trampoline)
159 move a0,s0
160 move a1,s1
161 jal _C_LABEL(fork_exit)
162 move a2,s2 #BDSlot
163
164 DO_AST
165
166 /*
167 * Since interrupts are enabled at this point, we use a1 instead of
168 * k0 or k1 to store the PCB pointer. This is because k0 and k1
169 * are not preserved across interrupts.
170 */
171 GET_CPU_PCPU(a1)
172 lw a1, PC_CURPCB(a1)
173 1:
174
175 mfc0 v0, COP_0_STATUS_REG # set exeption level bit.
176 or v0, SR_EXL
177 and v0, ~(SR_INT_ENAB)
178 mtc0 v0, COP_0_STATUS_REG # set exeption level bit.
179 nop
180 nop
181 nop
182 nop
183 .set noat
184 move k1, a1
185 RESTORE_U_PCB_REG(t0, MULLO, k1)
186 RESTORE_U_PCB_REG(t1, MULHI, k1)
187 mtlo t0
188 mthi t1
189 RESTORE_U_PCB_REG(a0, PC, k1)
190 RESTORE_U_PCB_REG(AT, AST, k1)
191 RESTORE_U_PCB_REG(v0, V0, k1)
192 _MTC0 a0, COP_0_EXC_PC # set return address
193
194 /*
195 * The use of k1 for storing the PCB pointer must be done only
196 * after interrupts are disabled. Otherwise it will get overwritten
197 * by the interrupt code.
198 */
199 RESTORE_U_PCB_REG(v1, V1, k1)
200 RESTORE_U_PCB_REG(a0, A0, k1)
201 RESTORE_U_PCB_REG(a1, A1, k1)
202 RESTORE_U_PCB_REG(a2, A2, k1)
203 RESTORE_U_PCB_REG(a3, A3, k1)
204 RESTORE_U_PCB_REG(t0, T0, k1)
205 RESTORE_U_PCB_REG(t1, T1, k1)
206 RESTORE_U_PCB_REG(t2, T2, k1)
207 RESTORE_U_PCB_REG(t3, T3, k1)
208 RESTORE_U_PCB_REG(t4, T4, k1)
209 RESTORE_U_PCB_REG(t5, T5, k1)
210 RESTORE_U_PCB_REG(t6, T6, k1)
211 RESTORE_U_PCB_REG(t7, T7, k1)
212 RESTORE_U_PCB_REG(s0, S0, k1)
213 RESTORE_U_PCB_REG(s1, S1, k1)
214 RESTORE_U_PCB_REG(s2, S2, k1)
215 RESTORE_U_PCB_REG(s3, S3, k1)
216 RESTORE_U_PCB_REG(s4, S4, k1)
217 RESTORE_U_PCB_REG(s5, S5, k1)
218 RESTORE_U_PCB_REG(s6, S6, k1)
219 RESTORE_U_PCB_REG(s7, S7, k1)
220 RESTORE_U_PCB_REG(t8, T8, k1)
221 RESTORE_U_PCB_REG(t9, T9, k1)
222 RESTORE_U_PCB_REG(k0, SR, k1)
223 RESTORE_U_PCB_REG(gp, GP, k1)
224 RESTORE_U_PCB_REG(s8, S8, k1)
225 RESTORE_U_PCB_REG(ra, RA, k1)
226 RESTORE_U_PCB_REG(sp, SP, k1)
227 mtc0 k0, COP_0_STATUS_REG # switch to user mode (when eret...)
228 HAZARD_DELAY
229 sync
230 eret
231 .set at
232 END(fork_trampoline)
233
234 /*
235 * Update pcb, saving current processor state.
236 * Note: this only works if pcbp != curproc's pcb since
237 * cpu_switch() will copy over pcb_context.
238 *
239 * savectx(struct pcb *pcbp);
240 */
241 LEAF(savectx)
242 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0)
243 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
244 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
245 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0)
246 mfc0 v0, COP_0_STATUS_REG
247 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0)
248 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0)
249 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0)
250 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0)
251 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0)
252 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0)
253 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0)
254 SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0)
255 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
256 /*
257 * FREEBSD_DEVELOPERS_FIXME:
258 * In case there are CPU-specific registers that need
259 * to be saved with the other registers do so here.
260 */
261 j ra
262 move v0, zero
263 END(savectx)
264
265
266 KSEG0TEXT_START;
267
268 NON_LEAF(mips_cpu_throw, STAND_FRAME_SIZE, ra)
269 mfc0 t0, COP_0_STATUS_REG # t0 = saved status register
270 nop
271 nop
272 and a3, t0, ~(SR_INT_ENAB)
273 mtc0 a3, COP_0_STATUS_REG # Disable all interrupts
274 ITLBNOPFIX
275 j mips_sw1 # We're not interested in old
276 # thread's context, so jump
277 # right to action
278 nop # BDSLOT
279 END(mips_cpu_throw)
280
281 /*
282 *XXX Fixme: should be written to new interface that requires lock
283 * storage. We fake it for now.
284 * cpu_switch(struct thread *old, struct thread *new);
285 * Find the highest priority process and resume it.
286 */
287 NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra)
288 mfc0 t0, COP_0_STATUS_REG # t0 = saved status register
289 nop
290 nop
291 and a3, t0, ~(SR_INT_ENAB)
292 mtc0 a3, COP_0_STATUS_REG # Disable all interrupts
293 ITLBNOPFIX
294 beqz a0, mips_sw1
295 move a3, a0
296 lw a0, TD_PCB(a0) # load PCB addr of curproc
297 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp
298 subu sp, sp, STAND_FRAME_SIZE
299 sw ra, STAND_RA_OFFSET(sp)
300 .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
301 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()'
302 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
303 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
304 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0)
305 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0)
306 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0)
307 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0)
308 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0)
309 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0)
310 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) # save return address
311 SAVE_U_PCB_CONTEXT(t0, PREG_SR, a0) # save status register
312 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
313 /*
314 * FREEBSD_DEVELOPERS_FIXME:
315 * In case there are CPU-specific registers that need
316 * to be saved with the other registers do so here.
317 */
318
319 sw a3, TD_LOCK(a0) # Switchout td_lock
320
321 mips_sw1:
322 #if defined(SMP) && defined(SCHED_ULE)
323 la t0, _C_LABEL(blocked_lock)
324 blocked_loop:
325 lw t1, TD_LOCK(a1)
326 beq t0, t1, blocked_loop
327 nop
328 #endif
329 move s7, a1 # Store newthread
330 /*
331 * Switch to new context.
332 */
333 GET_CPU_PCPU(a3)
334 sw a1, PC_CURTHREAD(a3)
335 lw a2, TD_PCB(a1)
336 sw a2, PC_CURPCB(a3)
337 lw v0, TD_REALKSTACK(a1)
338 li s0, (MIPS_KSEG2_START+VM_KERNEL_ALLOC_OFFSET) # If Uarea addr is below kseg2,
339 bltu v0, s0, sw2 # no need to insert in TLB.
340 lw a1, TD_UPTE+0(s7) # t0 = first u. pte
341 lw a2, TD_UPTE+4(s7) # t1 = 2nd u. pte
342 and s0, v0, PTE_ODDPG
343 beq s0, zero, entry0
344 nop
345
346 PANIC_KSEG0("USPACE sat on odd page boundary", t1)
347
348 /*
349 * Wiredown the USPACE of newproc in TLB entry#0. Check whether target
350 * USPACE is already in another place of TLB before that, and if so
351 * invalidate that TLB entry.
352 * NOTE: This is hard coded to UPAGES == 2.
353 * Also, there should be no TLB faults at this point.
354 */
355 entry0:
356 mtc0 v0, COP_0_TLB_HI # VPN = va
357 HAZARD_DELAY
358 tlbp # probe VPN
359 HAZARD_DELAY
360 mfc0 s0, COP_0_TLB_INDEX
361 nop
362 pgm:
363 bltz s0, entry0set
364 li t1, MIPS_KSEG0_START + 0x0fff0000 # invalidate tlb entry
365 sll s0, PAGE_SHIFT + 1
366 addu t1, s0
367 mtc0 t1, COP_0_TLB_HI
368 mtc0 zero, COP_0_TLB_LO0
369 mtc0 zero, COP_0_TLB_LO1
370 HAZARD_DELAY
371 tlbwi
372 HAZARD_DELAY
373 mtc0 v0, COP_0_TLB_HI # set VPN again
374 entry0set:
375 /* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */
376 mtc0 zero, COP_0_TLB_INDEX # TLB entry #0
377 # or a1, PG_G
378 mtc0 a1, COP_0_TLB_LO0 # upte[0]
379 # or a2, PG_G
380 mtc0 a2, COP_0_TLB_LO1 # upte[1]
381 HAZARD_DELAY
382 tlbwi # set TLB entry #0
383 HAZARD_DELAY
384 /*
385 * Now running on new u struct.
386 */
387 sw2:
388 la t1, _C_LABEL(pmap_activate) # s7 = new proc pointer
389 jalr t1 # s7 = new proc pointer
390 move a0, s7 # BDSLOT
391 /*
392 * Restore registers and return.
393 */
394 lw a0, TD_PCB(s7)
395 RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0)
396 RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context
397 RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0)
398 RESTORE_U_PCB_CONTEXT(s0, PREG_S0, a0)
399 RESTORE_U_PCB_CONTEXT(s1, PREG_S1, a0)
400 RESTORE_U_PCB_CONTEXT(s2, PREG_S2, a0)
401 RESTORE_U_PCB_CONTEXT(s3, PREG_S3, a0)
402 RESTORE_U_PCB_CONTEXT(s4, PREG_S4, a0)
403 RESTORE_U_PCB_CONTEXT(s5, PREG_S5, a0)
404 RESTORE_U_PCB_CONTEXT(s6, PREG_S6, a0)
405 RESTORE_U_PCB_CONTEXT(s7, PREG_S7, a0)
406 RESTORE_U_PCB_CONTEXT(sp, PREG_SP, a0)
407 RESTORE_U_PCB_CONTEXT(s8, PREG_S8, a0)
408 /*
409 * FREEBSD_DEVELOPERS_FIXME:
410 * In case there are CPU-specific registers that need
411 * to be restored with the other registers do so here.
412 */
413 mtc0 v0, COP_0_STATUS_REG
414 ITLBNOPFIX
415
416 j ra
417 nop
418 END(cpu_switch)
419 KSEG0TEXT_END;
420
421 /*----------------------------------------------------------------------------
422 *
423 * MipsSwitchFPState --
424 *
425 * Save the current state into 'from' and restore it from 'to'.
426 *
427 * MipsSwitchFPState(from, to)
428 * struct thread *from;
429 * struct trapframe *to;
430 *
431 * Results:
432 * None.
433 *
434 * Side effects:
435 * None.
436 *
437 *----------------------------------------------------------------------------
438 */
439 LEAF(MipsSwitchFPState)
440 mfc0 t1, COP_0_STATUS_REG # Save old SR
441 li t0, SR_COP_1_BIT # enable the coprocessor
442 mtc0 t0, COP_0_STATUS_REG
443 ITLBNOPFIX
444
445 beq a0, zero, 1f # skip save if NULL pointer
446 nop
447 /*
448 * First read out the status register to make sure that all FP operations
449 * have completed.
450 */
451 lw a0, TD_PCB(a0) # get pointer to pcb for proc
452 cfc1 t0, FPC_CSR # stall til FP done
453 cfc1 t0, FPC_CSR # now get status
454 li t3, ~SR_COP_1_BIT
455 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
456 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
457 and t2, t2, t3 # clear COP_1 enable bit
458 SAVE_U_PCB_REG(t2, PS, a0) # save new status register
459 /*
460 * Save the floating point registers.
461 */
462 SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
463 SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
464 SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
465 SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
466 SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
467 SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
468 SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
469 SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
470 SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
471 SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
472 SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
473 SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
474 SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
475 SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
476 SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
477 SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
478 SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
479 SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
480 SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
481 SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
482 SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
483 SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
484 SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
485 SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
486 SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
487 SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
488 SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
489 SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
490 SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
491 SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
492 SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
493 SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
494
495 1:
496 /*
497 * Restore the floating point registers.
498 */
499 RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register
500 RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
501 RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
502 RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
503 RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
504 RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
505 RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
506 RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
507 RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
508 RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
509 RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
510 RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
511 RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
512 RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
513 RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
514 RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
515 RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
516 RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
517 RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
518 RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
519 RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
520 RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
521 RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
522 RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
523 RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
524 RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
525 RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
526 RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
527 RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
528 RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
529 RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
530 RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
531 RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
532
533 and t0, t0, ~FPC_EXCEPTION_BITS
534 ctc1 t0, FPC_CSR
535 nop
536
537 mtc0 t1, COP_0_STATUS_REG # Restore the status register.
538 ITLBNOPFIX
539 j ra
540 nop
541 END(MipsSwitchFPState)
542
543 /*----------------------------------------------------------------------------
544 *
545 * MipsSaveCurFPState --
546 *
547 * Save the current floating point coprocessor state.
548 *
549 * MipsSaveCurFPState(td)
550 * struct thread *td;
551 *
552 * Results:
553 * None.
554 *
555 * Side effects:
556 * machFPCurProcPtr is cleared.
557 *
558 *----------------------------------------------------------------------------
559 */
560 LEAF(MipsSaveCurFPState)
561 lw a0, TD_PCB(a0) # get pointer to pcb for thread
562 mfc0 t1, COP_0_STATUS_REG # Disable interrupts and
563 li t0, SR_COP_1_BIT # enable the coprocessor
564 mtc0 t0, COP_0_STATUS_REG
565 ITLBNOPFIX
566 GET_CPU_PCPU(a1)
567 sw zero, PC_FPCURTHREAD(a1) # indicate state has been saved
568 /*
569 * First read out the status register to make sure that all FP operations
570 * have completed.
571 */
572 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
573 li t3, ~SR_COP_1_BIT
574 and t2, t2, t3 # clear COP_1 enable bit
575 cfc1 t0, FPC_CSR # stall til FP done
576 cfc1 t0, FPC_CSR # now get status
577 SAVE_U_PCB_REG(t2, PS, a0) # save new status register
578 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
579 /*
580 * Save the floating point registers.
581 */
582 SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
583 SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
584 SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
585 SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
586 SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
587 SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
588 SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
589 SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
590 SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
591 SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
592 SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
593 SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
594 SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
595 SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
596 SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
597 SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
598 SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
599 SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
600 SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
601 SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
602 SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
603 SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
604 SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
605 SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
606 SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
607 SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
608 SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
609 SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
610 SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
611 SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
612 SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
613 SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
614
615 mtc0 t1, COP_0_STATUS_REG # Restore the status register.
616 ITLBNOPFIX
617 j ra
618 nop
619 END(MipsSaveCurFPState)
620
621 /*
622 * When starting init, call this to configure the process for user
623 * mode. This will be inherited by other processes.
624 */
625 LEAF_NOPROFILE(prepare_usermode)
626 j ra
627 nop
628 END(prepare_usermode)
629
630
631 /*
632 * This code is copied the user's stack for returning from signal handlers
633 * (see sendsig() and sigreturn()). We have to compute the address
634 * of the sigcontext struct for the sigreturn call.
635 */
636 .globl _C_LABEL(sigcode)
637 _C_LABEL(sigcode):
638 addu a0, sp, SIGF_UC # address of ucontext
639 li v0, SYS_sigreturn
640 # sigreturn (ucp)
641 syscall
642 break 0 # just in case sigreturn fails
643 .globl _C_LABEL(esigcode)
644 _C_LABEL(esigcode):
645
646 .data
647 .globl szsigcode
648 szsigcode:
649 .long esigcode-sigcode
650 .text
Cache object: 8cd7e43d0af870b1c134c33dcf589855
|