patch-2.4.0-test10 linux/arch/i386/kernel/i387.c
Next file: linux/arch/i386/kernel/i8259.c
Previous file: linux/arch/i386/kernel/entry.S
Back to the patch index
Back to the overall index
- Lines: 75
- Date:
Mon Oct 23 15:57:29 2000
- Orig file:
v2.4.0-test9/linux/arch/i386/kernel/i387.c
- Orig date:
Sun Sep 3 10:57:33 2000
diff -u --recursive --new-file v2.4.0-test9/linux/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c
@@ -33,22 +33,24 @@
#endif
/*
- * FPU lazy state save handling.
+ * The _current_ task is using the FPU for the first time
+ * so initialize it and set the mxcsr to its default
+ * value at reset if we support FXSR and then
+ * remeber the current task has used the FPU.
*/
-
-void save_fpu( struct task_struct *tsk )
+void init_fpu(void)
{
- if ( HAVE_FXSR ) {
- asm volatile( "fxsave %0 ; fwait"
- : "=m" (tsk->thread.i387.fxsave) );
- } else {
- asm volatile( "fnsave %0 ; fwait"
- : "=m" (tsk->thread.i387.fsave) );
- }
- tsk->flags &= ~PF_USEDFPU;
- stts();
+ __asm__("fninit");
+ if ( HAVE_FXSR )
+ load_mxcsr(0x1f80);
+
+ current->used_math = 1;
}
+/*
+ * FPU lazy state save handling.
+ */
+
void save_init_fpu( struct task_struct *tsk )
{
if ( HAVE_FXSR ) {
@@ -79,16 +81,16 @@
static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
{
- unsigned short ret = 0;
- int i;
-
- for ( i = 0 ; i < 8 ; i++ ) {
- if ( (twd & 0x3) != 0x3 ) {
- ret |= (1 << i);
- }
- twd = twd >> 2;
- }
- return ret;
+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */
+ tmp = ~twd;
+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+ /* and move the valid bits to the lower byte. */
+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+ return tmp;
}
static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave )
@@ -105,8 +107,8 @@
if ( twd & 0x1 ) {
st = (struct _fpxreg *) FPREG_ADDR( fxsave, i );
- switch ( st->exponent ) {
- case 0xffff:
+ switch ( st->exponent & 0x7fff ) {
+ case 0x7fff:
tag = 2; /* Special */
break;
case 0x0000:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)