123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- /*
- * r2300_switch.S: R2300 specific task switching code.
- *
- * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
- * Copyright (C) 1994, 1995, 1996 by Andreas Busse
- *
- * Multi-cpu abstraction and macros for easier reading:
- * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- *
- * Further modifications to make this work:
- * Copyright (c) 1998-2000 Harald Koerfgen
- */
- #include <asm/asm.h>
- #include <asm/cachectl.h>
- #include <asm/fpregdef.h>
- #include <asm/mipsregs.h>
- #include <asm/asm-offsets.h>
- #include <asm/regdef.h>
- #include <asm/stackframe.h>
- #include <asm/thread_info.h>
- #include <asm/asmmacro.h>
- .set mips1
- .align 5
- /*
- * 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)
- /*
- * FPU context is saved iff the process has used it's FPU in the current
- * time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user
- * space STATUS register should be 0, so that a process *always* starts its
- * userland with FPU disabled after each context switch.
- *
- * FPU will be enabled as soon as the process accesses FPU again, through
- * do_cpu() trap.
- */
- /*
- * task_struct *resume(task_struct *prev, task_struct *next,
- * struct thread_info *next_ti, int usedfpu)
- */
- LEAF(resume)
- mfc0 t1, CP0_STATUS
- sw t1, THREAD_STATUS(a0)
- cpu_save_nonscratch a0
- sw ra, THREAD_REG31(a0)
- beqz a3, 1f
- PTR_L t3, TASK_THREAD_INFO(a0)
- /*
- * clear saved user stack CU1 bit
- */
- lw t0, ST_OFF(t3)
- li t1, ~ST0_CU1
- and t0, t0, t1
- sw t0, ST_OFF(t3)
- fpu_save_single a0, t0 # clobbers t0
- 1:
- #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
- PTR_LA t8, __stack_chk_guard
- LONG_L t9, TASK_STACK_CANARY(a1)
- LONG_S t9, 0(t8)
- #endif
- /*
- * 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
- addiu t1, $28, _THREAD_SIZE - 32
- sw t1, kernelsp
- mfc0 t1, CP0_STATUS /* Do we really need this? */
- li a3, 0xff01
- and t1, a3
- lw 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)
- /*
- * Save a thread's fp context.
- */
- LEAF(_save_fp)
- fpu_save_single a0, t1 # clobbers t1
- jr ra
- END(_save_fp)
- /*
- * Restore a thread's fp context.
- */
- LEAF(_restore_fp)
- fpu_restore_single a0, t1 # clobbers t1
- jr ra
- END(_restore_fp)
- /*
- * 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.
- *
- * The value to initialize fcr31 to comes in $a0.
- */
- .set push
- SET_HARDFLOAT
- LEAF(_init_fpu)
- mfc0 t0, CP0_STATUS
- li t1, ST0_CU1
- or t0, t1
- mtc0 t0, CP0_STATUS
- ctc1 a0, fcr31
- li t0, -1
- mtc1 t0, $f0
- mtc1 t0, $f1
- mtc1 t0, $f2
- mtc1 t0, $f3
- mtc1 t0, $f4
- mtc1 t0, $f5
- mtc1 t0, $f6
- mtc1 t0, $f7
- mtc1 t0, $f8
- mtc1 t0, $f9
- mtc1 t0, $f10
- mtc1 t0, $f11
- mtc1 t0, $f12
- mtc1 t0, $f13
- mtc1 t0, $f14
- mtc1 t0, $f15
- mtc1 t0, $f16
- mtc1 t0, $f17
- mtc1 t0, $f18
- mtc1 t0, $f19
- mtc1 t0, $f20
- mtc1 t0, $f21
- mtc1 t0, $f22
- mtc1 t0, $f23
- mtc1 t0, $f24
- mtc1 t0, $f25
- mtc1 t0, $f26
- mtc1 t0, $f27
- mtc1 t0, $f28
- mtc1 t0, $f29
- mtc1 t0, $f30
- mtc1 t0, $f31
- jr ra
- END(_init_fpu)
- .set pop
|