patch-2.1.73 linux/arch/i386/math-emu/fpu_etc.c

Next file: linux/arch/i386/math-emu/fpu_proto.h
Previous file: linux/arch/i386/math-emu/fpu_entry.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.72/linux/arch/i386/math-emu/fpu_etc.c linux/arch/i386/math-emu/fpu_etc.c
@@ -3,9 +3,9 @@
  |                                                                           |
  | Implement a few FPU instructions.                                         |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997                                         |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@suburbia.net             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -17,102 +17,116 @@
 #include "reg_constant.h"
 
 
-static void fchs(FPU_REG *st0_ptr)
+static void fchs(FPU_REG *st0_ptr, u_char st0tag)
 {
-  if ( st0_ptr->tag ^ TW_Empty )
+  if ( st0tag ^ TAG_Empty )
     {
-      st0_ptr->sign ^= SIGN_POS^SIGN_NEG;
+      signbyte(st0_ptr) ^= SIGN_NEG;
       clear_C1();
     }
   else
-    stack_underflow();
+    FPU_stack_underflow();
 }
 
-static void fabs(FPU_REG *st0_ptr)
+
+static void fabs(FPU_REG *st0_ptr, u_char st0tag)
 {
-  if ( st0_ptr->tag ^ TW_Empty )
+  if ( st0tag ^ TAG_Empty )
     {
-      st0_ptr->sign = SIGN_POS;
+      setpositive(st0_ptr);
       clear_C1();
     }
   else
-    stack_underflow();
+    FPU_stack_underflow();
 }
 
 
-static void ftst_(FPU_REG *st0_ptr)
+static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
 {
-  switch (st0_ptr->tag)
+  switch (st0tag)
     {
-    case TW_Zero:
+    case TAG_Zero:
       setcc(SW_C3);
       break;
-    case TW_Valid:
-      if (st0_ptr->sign == SIGN_POS)
+    case TAG_Valid:
+      if (getsign(st0_ptr) == SIGN_POS)
         setcc(0);
       else
         setcc(SW_C0);
-
-#ifdef DENORM_OPERAND
-      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+      break;
+    case TAG_Special:
+      switch ( FPU_Special(st0_ptr) )
 	{
+	case TW_Denormal:
+	  if (getsign(st0_ptr) == SIGN_POS)
+	    setcc(0);
+	  else
+	    setcc(SW_C0);
+	  if ( denormal_operand() < 0 )
+	    {
 #ifdef PECULIAR_486
-	  /* This is weird! */
-	  if (st0_ptr->sign == SIGN_POS)
-	    setcc(SW_C3);
+	      /* This is weird! */
+	      if (getsign(st0_ptr) == SIGN_POS)
+		setcc(SW_C3);
 #endif PECULIAR_486
-	  return;
+	      return;
+	    }
+	  break;
+	case TW_NaN:
+	  setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
+	  EXCEPTION(EX_Invalid);
+	  break;
+	case TW_Infinity:
+	  if (getsign(st0_ptr) == SIGN_POS)
+	    setcc(0);
+	  else
+	    setcc(SW_C0);
+	  break;
+	default:
+	  setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
+	  EXCEPTION(EX_INTERNAL|0x14);
+	  break;
 	}
-#endif DENORM_OPERAND
-
-      break;
-    case TW_NaN:
-      setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
-      EXCEPTION(EX_Invalid);
-      break;
-    case TW_Infinity:
-      if (st0_ptr->sign == SIGN_POS)
-        setcc(0);
-      else
-        setcc(SW_C0);
       break;
-    case TW_Empty:
+    case TAG_Empty:
       setcc(SW_C0|SW_C2|SW_C3);
       EXCEPTION(EX_StackUnder);
       break;
-    default:
-      setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
-      EXCEPTION(EX_INTERNAL|0x14);
-      break;
     }
 }
 
-static void fxam(FPU_REG *st0_ptr)
+
+static void fxam(FPU_REG *st0_ptr, u_char st0tag)
 {
-  int c=0;
-  switch (st0_ptr->tag)
+  int c = 0;
+  switch (st0tag)
     {
-    case TW_Empty:
+    case TAG_Empty:
       c = SW_C3|SW_C0;
       break;
-    case TW_Zero:
+    case TAG_Zero:
       c = SW_C3;
       break;
-    case TW_Valid:
-      /* This will need to be changed if TW_Denormal is ever used. */
-      if ( st0_ptr->exp <= EXP_UNDER )
-        c = SW_C2|SW_C3;  /* Denormal */
-      else
-        c = SW_C2;
-      break;
-    case TW_NaN:
-      c = SW_C0;
-      break;
-    case TW_Infinity:
-      c = SW_C2|SW_C0;
+    case TAG_Valid:
+      c = SW_C2;
       break;
+    case TAG_Special:
+      switch ( FPU_Special(st0_ptr) )
+	{
+	case TW_Denormal:
+	  c = SW_C2|SW_C3;  /* Denormal */
+	  break;
+	case TW_NaN:
+	  /* We also use NaN for unsupported types. */
+	  if ( (st0_ptr->sigh & 0x80000000) && (exponent(st0_ptr) == EXP_OVER) )
+	    c = SW_C0;
+	  break;
+	case TW_Infinity:
+	  c = SW_C2|SW_C0;
+	  break;
+	}
     }
-  if (st0_ptr->sign == SIGN_NEG)
+  if ( getsign(st0_ptr) == SIGN_NEG )
     c |= SW_C1;
   setcc(c);
 }
@@ -123,7 +137,7 @@
   ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal
 };
 
-void fp_etc()
+void FPU_etc()
 {
-  (fp_etc_table[FPU_rm])(&st(0));
+  (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0());
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov