1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1994, 1995, 1996, 1998, 1999 by Ralf Baechle 7 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 8 * Copyright (C) 1994, 1995, 1996, by Andreas Busse 9 * Copyright (C) 1999 Silicon Graphics, Inc. 10 */ 11#include <asm/asm.h> 12#include <asm/cachectl.h> 13#include <asm/fpregdef.h> 14#include <asm/mipsregs.h> 15#include <asm/offset.h> 16#include <asm/page.h> 17#include <asm/pgtable.h> 18#include <asm/processor.h> 19#include <asm/regdef.h> 20#include <asm/stackframe.h> 21 22#include <asm/asmmacro.h> 23 24 .set mips3 25 26#define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ 27#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) 28 29/* 30 * [jsun] FPU context is saved if and only if the process has used FPU in 31 * the current run (PF_USEDFPU). In any case, the CU1 bit for user space 32 * STATUS register should be 0, so that a process *always* starts its 33 * userland with FPU disabled after each context switch. 34 * 35 * FPU will be enabled as soon as the process accesses FPU again, through 36 * do_cpu() trap. 37 */ 38 39/* 40 * task_struct *resume(task_struct *prev, task_struct *next) 41 */ 42 .set noreorder 43 .align 5 44 LEAF(resume) 45 mfc0 t1, CP0_STATUS 46 sd t1, THREAD_STATUS(a0) 47 cpu_save_nonscratch a0 48 sd ra, THREAD_REG31(a0) 49 50 /* 51 * check if we need to save FPU registers 52 */ 53 ld t0, TASK_FLAGS(a0) 54 li t1, PF_USEDFPU 55 and t2, t0, t1 56 beqz t2, 1f 57 nor t1, zero, t1 58 59 /* 60 * clear PF_USEDFPU bit in task flags 61 */ 62 and t0, t0, t1 63 sd t0, TASK_FLAGS(a0) 64 65 /* 66 * clear saved user stack CU1 bit 67 */ 68 ld t0, ST_OFF(a0) 69 li t1, ~ST0_CU1 70 and t0, t0, t1 71 sd t0, ST_OFF(a0) 72 73 74 sll t2, t0, 5 75 bgez t2, 2f 76 sdc1 $f0, (THREAD_FPU + 0x00)(a0) 77 fpu_save_16odd a0 782: 79 fpu_save_16even a0 t1 # clobbers t1 801: 81 82 /* 83 * The order of restoring the registers takes care of the race 84 * updating $28, $29 and kernelsp without disabling ints. 85 */ 86 move $28, a1 87 cpu_restore_nonscratch $28 88 89 daddiu a1, $28, KERNEL_STACK_SIZE-32 90 set_saved_sp a1, t0, t1 91 92 mfc0 t1, CP0_STATUS /* Do we really need this? */ 93 li a3, 0xff00 94 and t1, a3 95 ld a2, THREAD_STATUS($28) 96 nor a3, $0, a3 97 and a2, a3 98 or a2, t1 99 mtc0 a2, CP0_STATUS 100 jr ra 101 move v0, a0 102 END(resume) 103 104/* 105 * Save a thread's fp context. 106 */ 107 .set noreorder 108LEAF(_save_fp) 109 mfc0 t0, CP0_STATUS 110 sll t1, t0, 5 111 bgez t1, 1f # 16 register mode? 112 nop 113 fpu_save_16odd a0 1141: 115 fpu_save_16even a0 t1 # clobbers t1 116 jr ra 117 sdc1 $f0, (THREAD_FPU + 0x00)(a0) 118 END(_save_fp) 119 120/* 121 * Restore a thread's fp context. 122 */ 123LEAF(_restore_fp) 124 mfc0 t0, CP0_STATUS 125 sll t1, t0, 5 126 bgez t1, 1f # 16 register mode? 127 nop 128 129 fpu_restore_16odd a0 1301: 131 fpu_restore_16even a0, t0 # clobbers t0 132 133 jr ra 134 ldc1 $f0, (THREAD_FPU + 0x00)(a0) 135 END(_restore_fp) 136 137/* 138 * Load the FPU with signalling NANS. This bit pattern we're using has 139 * the property that no matter whether considered as single or as double 140 * precision represents signaling NANS. 141 * 142 * We initialize fcr31 to rounding to nearest, no exceptions. 143 */ 144 145#define FPU_DEFAULT 0x00000000 146 147LEAF(_init_fpu) 148 mfc0 t0, CP0_STATUS 149 li t1, ST0_CU1 150 or t0, t1 151 mtc0 t0, CP0_STATUS 152 FPU_ENABLE_HAZARD 153 sll t0, t0, 5 154 155 li t1, FPU_DEFAULT 156 ctc1 t1, fcr31 157 158 bgez t0, 1f # 16 / 32 register mode? 159 li t0, -1 160 161 dmtc1 t0, $f1 162 dmtc1 t0, $f3 163 dmtc1 t0, $f5 164 dmtc1 t0, $f7 165 dmtc1 t0, $f9 166 dmtc1 t0, $f11 167 dmtc1 t0, $f13 168 dmtc1 t0, $f15 169 dmtc1 t0, $f17 170 dmtc1 t0, $f19 171 dmtc1 t0, $f21 172 dmtc1 t0, $f23 173 dmtc1 t0, $f25 174 dmtc1 t0, $f27 175 dmtc1 t0, $f29 176 dmtc1 t0, $f31 177 1781: dmtc1 t0, $f0 179 dmtc1 t0, $f2 180 dmtc1 t0, $f4 181 dmtc1 t0, $f6 182 dmtc1 t0, $f8 183 dmtc1 t0, $f10 184 dmtc1 t0, $f12 185 dmtc1 t0, $f14 186 dmtc1 t0, $f16 187 dmtc1 t0, $f18 188 dmtc1 t0, $f20 189 dmtc1 t0, $f22 190 dmtc1 t0, $f24 191 dmtc1 t0, $f26 192 dmtc1 t0, $f28 193 jr ra 194 dmtc1 t0, $f30 195 END(_init_fpu) 196

